Суммируйте вложенные значения с помощью Linq - PullRequest
12 голосов
/ 05 мая 2011

Простая проблема: у меня есть пользователи, которые могут иметь много заказов, которые могут иметь много продуктов. Как выглядит запрос Linq (лямбда), чтобы получить общий итог пользователя по всем значениям Product.Price?

Я пробовал это:

int total = users.Sum(u => u.Orders.Sum(o => o.Products.Sum(p => p.Price)));

Но это дает мне:

Ошибка приведения к типу значения 'Int32', поскольку материализованное значение равно нулю. Либо универсальный параметр типа результата, либо запрос должен использовать обнуляемый тип.

Конечно, пользователь не может иметь никаких заказов, и в заказе не может быть никаких продуктов. Но Product.Price не является недействительным значением.

Итак, я попробовал это, думая, что он задыхается от пустых коллекций:

int total = users.Sum(u => u.Orders.Sum(o => o.Products.Sum(p => p.Price) ?? 0) ?? 0) ?? 0;

Но он выдает ошибки компиляции, говоря, что левая сторона ?? не имеет значения null.

Что я делаю не так?

Заранее спасибо.

ОБНОВЛЕНИЕ: рабочая версия моих примеров выше после использования логики Марка из его ответа:

int total = users.Sum(u => u.Orders.Sum(o => o.Products.Sum(p => (int?)p.Price))) ?? 0;

1 Ответ

30 голосов
/ 05 мая 2011
int total = (from user in users
             from order in user.Orders
             from product in order.Products
             select (int?)product.Price).Sum() ?? 0;

будет моим подношением; есть досадный сбой в том, что SUM в SQL по 0 строкам равно NULL, а не 0 - вышеупомянутое обходит это.

или как лямбды (из комментариев):

int total = users.SelectMany(user => user.Orders)
                 .SelectMany(order => order.Products)
                 .Sum(product => (int?)product.Price) ?? 0;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...