Помещение номера заказа в элементы в запросе linq - PullRequest
0 голосов
/ 16 марта 2011

У меня следующий запрос Linq. TransactionData является IEnumerable.

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?

Ответы [ 2 ]

1 голос
/ 16 марта 2011

Еще один способ думать об этом состоит в том, что у вас есть две последовательности:

  1. Транзакции
  2. индекс "автоинкремент"

получить одну последовательность транзакций с идентификаторами.Когда мы хотим объединить две последовательности, мы можем использовать оператор 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 объединяет две последовательности, пока не достигнет концаодна из последовательностей.Вот почему все хорошо, Enumberable.Range, чтобы получить гораздо больший диапазон чисел, чем нам на самом деле нужно.

1 голос
/ 16 марта 2011

Проблема в том, что вы закрываете переменную totalTransactions, вам нужно создать локальную копию для использования. Проверьте Закрытие по переменной цикла, которое считается вредным для более подробного объяснения.

Примерно так должно работать:

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++;
}
...