2011-03-16 39 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