Суммирование вложенных значений с помощью Linq

#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. Спасибо, это именно то, что мне было нужно. Я также опубликовал альтернативный вариант выше (модифицированная версия моей первоначальной попытки).