#c# #linq #lambda
#c# #linq #лямбда
Вопрос:
Простая проблема: у меня есть пользователи, у которых может быть много заказов, у которых может быть много продуктов. Как выглядит запрос Linq (lambda) для получения общего количества всех продуктов пользователя.Значения цен?
Я пробовал это:
int total = users.Sum(u => u.Orders.Sum(o => o.Products.Sum(p => p.Price)));
Но это дает мне:
Приведение к значению типа ‘Int32’ завершилось неудачей, поскольку материализованное значение равно null. Либо общий параметр типа результата, либо запрос должны использовать тип с нулевым значением.
Конечно, у пользователя может не быть никаких заказов, а в заказе может не быть никаких продуктов. Но продукт.Цена не является обнуляемым значением.
Итак, я попробовал это, думая, что это захлебывается пустыми коллекциями:
int total = users.Sum(u => u.Orders.Sum(o => o.Products.Sum(p => p.Price) ?? 0) ?? 0) ?? 0;
Но это выдает ошибки компиляции, говоря, что левая часть ??
не обнуляется.
Что я делаю не так?
Заранее спасибо.
ОБНОВЛЕНИЕ: рабочая версия моих примеров выше после использования логики Марка из его ответа:
int total = users.Sum(u => u.Orders.Sum(o => o.Products.Sum(p => (int?)p.Price))) ?? 0;
Ответ №1:
int total = (from user in users
from order in user.Orders
from product in order.Products
select (int?)product.Price).Sum() ?? 0;
было бы моим предложением; есть досадный сбой, заключающийся в том, что СУММА в SQL по 0 строкам равна NULL
, а не 0
— вышеуказанное работает вокруг этого.
или в виде лямбд (из комментариев):
int total = users.SelectMany(user => user.Orders)
.SelectMany(order => order.Products)
.Sum(product => (int?)product.Price) ?? 0;
Комментарии:
1. Спасибо, это именно то, что мне было нужно. Я также опубликовал альтернативный вариант выше (модифицированная версия моей первоначальной попытки).