2011-03-16 43 views
0

我有以下Linq查询。 transactionData是一个IEnumerable。在linq查询中的商品上放置订单号

var totalTransactions = 0; 
viewModel.GroupedTransactions = transactionData 
    .GroupBy(x => new { DocumentId = x.DocumentId ?? "Un Documented" }) 
    .Select(x => new GroupedTransaction 
    { 
     DocumentId = x.Key.DocumentId, 
     Transactions = x.Select(y => new Transaction 
     { 
      Amount = y.CommitAmount, 
      ActivityType = y.ActivityType, 
      Number = totalTransactions++ 
     }) 
    }) 
    .OrderBy(x => x.DocumentId); 

其中我试图将交易记录上的数字设置为递增的数字。 这不起作用,在数字中留下空白。

我也在查询后试过以下内容。

foreach (var item in viewModel.GroupedTransactions.SelectMany(x => x.Transactions)) 
{ 
    item.Number = totalTransactions; 
    totalTransactions++; 
} 

这甚至没有更新数值。 我做错了什么,或者有一个简单的方法,用一个整洁的linq扩展方法?

+1

哦,我的,你在一个LINQ'Select'中的对象初始化器中增加一个变量! – 2011-03-16 01:35:47

回答

1

问题是您正在关闭变量totalTransactions,您必须创建一个本地副本才能使用。 Check Closing over the loop variable considered harmful获取更详细的解释。

像这样的东西应该工作:

var totalTransactions = 0; 
viewModel.GroupedTransactions = transactionData 
    .GroupBy(x => new { DocumentId = x.DocumentId ?? "Un Documented" }) 
    .Select(x => 
    { 
     new GroupedTransaction() 
     { 
     DocumentId = x.Key.DocumentId, 
     Transactions = x.Select(y => 
     { 
      var currentTransactionId = totalTransactions; 
      totalTransactions++; 

      return new Transaction 
      { 
      Amount = y.CommitAmount, 
      ActivityType = y.ActivityType, 
      Number = currentTransactionId 
      } 
     }) 
     } 
    }) 
    .OrderBy(x => x.DocumentId); 

为了您与foreach循环第二种方法 - 你实际上是在创建一个新的枚举与SelectMany()您后来只是扔掉:

foreach (var item in viewModel.GroupedTransactions.SelectMany(x => x.Transactions)) 
{ 
    item.Number = totalTransactions; 
    totalTransactions++; 
} 

相反您必须通过使用ToList()来强制对您的收藏进行急切的评估,以创建可以安全修改的收藏。

var transactions = viewModel.GroupedTransactions 
          .SelectMany(x => x.Transactions) 
          .ToList(); 
foreach (var item in transactions) 
{ 
    item.Number = totalTransactions; 
    totalTransactions++; 
} 
+0

仍然得到相同的结果。根据组中有多少人留下数字中的空白。这真的很奇怪。 – Schotime 2011-03-16 01:58:51

+0

你看到了什么数字?我用一些简化的示例代码证实了这一点应该起作用 – BrokenGlass 2011-03-16 02:15:49

+0

一旦我把ToList()放在了这两个工作中。干杯。 – Schotime 2011-03-16 03:26:16

1

另一种方式去思考它,你有两个序列:

  1. 交易
  2. “自动递增”指数

而且你想获得一个序列,交易与ids。当我们想两个序列结合,我们可以使用Zip操作:

viewModel.GroupedTransactions = transactionData  
    .GroupBy(x => new { DocumentId = x.DocumentId ?? "Un Documented" }) 
    .Zip(Enumerable.Range(0, int.MaxValue), (x, index) => new GroupedTransaction  
    {   
     DocumentId = x.Key.DocumentId,   
     Transactions = x.Select(y => new Transaction   
     {    
      Amount = y.CommitAmount,    
      ActivityType = y.ActivityType,    
      Number = index   
     })  
    })  
    .OrderBy(x => x.DocumentId); 

这是你脑子里有什么?

Zip将两个序列组合到一个序列的末尾。这就是为什么它可以允许。范围比我们实际需要的范围大得多。

+0

听起来很好克里斯,但邮政是在dotnet 4.0我相信,我现在还不能支持。 – Schotime 2011-03-16 02:13:08

+0

@Schotime那很不幸,但它[很容易在3.0中实现](http://stackoverflow.com/questions/2427015/how-to-do-pythons-zip-in-c/2427087#2427087)并且相当公平对周围有用。 – 2011-03-16 02:26:21