Почему значения из моих запросов linq не появляются сразу? - PullRequest
5 голосов
/ 07 марта 2011

У меня есть следующий блок запросов linq для вычисления некоторых значений для отчета.

var items = (from trans in calclabordb.Sales_Transactions                
             select trans).SelectMany(st => st.Sales_TransactionLineItems).Where(stli => stli.TypeID == typeID);

decimal test = items.Where(stli => stli.Inventory_Item is Base).Sum(stli => (decimal?)stli.Inventory_Item.IntExtraServiceAmount) ?? 0;
decimal test2 = items.Where(stli => stli.Inventory_Item is Extra).Sum(stli => (decimal?)stli.ItemPrice) ?? 0;
decimal test3 = test + test2;
current.ExtraSales = items.Where(stli => stli.Inventory_Item is Base).Sum(stli => (decimal?)stli.Inventory_Item.IntExtraServiceAmount) ?? 0 +
    items.Where(stli => stli.Inventory_Item is Extra).Sum(stli => (decimal?)stli.ItemPrice) ?? 0;

Я прошел по коду в отладчике и заметил некоторые странности.После присвоения в test его значение равно 0. После присвоения в test2 test2 == 0 и test == 11.31 после присвоения в test3 test == 11.31 test2 == 11.28 и test3 == 22.59 после присвоения в ExtraSales ExtraSales == 11.31.Значение в ExtraSales после завершения должно составлять 22,59.Что здесь происходит?

РЕДАКТИРОВАТЬ: я добавил дополнительные строки после присваивания в ExtraSales, но значение не меняется.

Ответы [ 3 ]

22 голосов
/ 07 марта 2011

Ответы, в которых говорится, что это проблема отложенного выполнения, неверны. Это проблема приоритета оператора.

Избавьтесь от всего этого совершенно неуместного и недоступного для чтения кода. Это все красная сельдь. Соответствующее воспроизведение:

decimal? d1 = 11.31m;
decimal? d2 = 11.28m;
decimal test1 = d1 ?? 0m;
decimal test2 = d2 ?? 0m;
decimal test3 = test1 + test2;
decimal test4 = d1 ?? 0m + d2 ?? 0m;

Что означает последняя строка? Означает ли это то же самое, что и строка перед ним?

Нет, это не так. Оператор сложения имеет более высокий приоритет , чем оператор объединения нулей, так что это

decimal test4 = d1 ?? (0m + d2) ?? 0m;

Код, который вы написали, означает «произвести значение d1, если d1 не равно нулю. Если d1 равно нулю, а 0m + d2 не равно нулю, тогда выведите значение 0m + d2. Если 0m + d2 равно нулю, то получите значение 0й. "

(Возможно, вы не знали, что у оператора ?? есть это приятное свойство цепочки. В общем, a ?? b ?? c ?? d ?? e дает вам первое ненулевое значение a, b, c или d и e, если все они в противном случае все null. Вы можете делать цепочку сколько угодно. Это довольно элегантный маленький оператор.)

Поскольку d1 не равно нулю, мы создаем его значение, и test4 присваивается значение d1.

Вы, вероятно, хотели сказать:

decimal test4 = (d1 ?? 0m) + (d2 ?? 0m);

Если вы имеете в виду «d1 или d2 могут быть нулевыми, а если любой из них, то трактуйте нулевой как ноль». Таким образом, 12 + 2 равно 14, 12 + ноль равно 12, ноль + ноль равно 0

Если вы имеете в виду «либо d1 и d2 могут быть нулевыми, а если либо нулевым, то я хочу ноль», то это

  decimal test4 = (d1 + d2) ?? 0m;

Итак, 12 + 2 равно 14, 12 + ноль равно 0, ноль + ноль равно 0

Хочу заметить, что если бы вы отформатировали свой код так, чтобы соответствующий текст был на экране, вы, вероятно, не получили бы пять или около того неправильных ответов, опубликованных первыми. Попробуйте отформатировать свой код так, чтобы все это было на экране; Вы получите лучшие ответы, если вы это сделаете.

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

Я думаю, что вы «жертва» отложенного выполнения в LINQ. Прочтите этот пост в блоге, который объясняет концепцию:

http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx

0 голосов
/ 07 марта 2011

Да, это называется отложенным исполнением, и это одна из вещей, которая может быть очень мощной, но также сбивает вас с толку, если вы этого не ожидаете ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...