Linq-запрос с нулевой суммой - PullRequest
67 голосов
/ 30 марта 2009
from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId
              select v.Points).Sum()
}

Я получил этот запрос, но он не работает, если не найдено ни одного голоса за исключением:

The null value cannot be assigned to a member with type System.Int32 which is a non-nullable value type.

Я предполагаю, потому что sum возвращает int, а не nullable int, давая сумме int? поскольку входные данные выдают только ту же ошибку, вероятно, сумма действует только на целые числа.

Есть ли хороший обходной путь для этого?

Ответы [ 15 ]

73 голосов
/ 10 февраля 2010

Вы хотите использовать пустую форму Sum, поэтому попробуйте привести свое значение к значению nullable:

from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId
              select v.Points).Sum(r => (decimal?) r.Points)
}

Ваша проблема обсуждается здесь более подробно:

http://weblogs.asp.net/zeeshanhirani/archive/2008/07/15/applying-aggregates-to-empty-collections-causes-exception-in-linq-to-sql.aspx

22 голосов
/ 30 марта 2009
from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId
              select v.Points ?? 0).Sum() 
}

РЕДАКТИРОВАТЬ - хорошо, как насчет этого ... (Снова снимать, поскольку я не знаю вашу модель ...):

from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId)
              .Sum(v => v.Points) 
}
19 голосов
/ 13 декабря 2010

Предполагая, что "v.Points" является десятичным числом, просто используйте следующее:

from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId
              select (decimal?) v.Points).Sum() ?? 0
}
11 голосов
/ 16 октября 2010

Если вам не нравится приведение к десятичному nullabe, вы также можете попробовать использовать Linq To Objects с методом ToList (),

LinqToObjects Сумма пустой коллекции равна 0, где LinqToSql Сумма пустой коллекции равна нулю.

10 голосов
/ 19 апреля 2012

Попробуйте проверить это:

var count = db.Cart.Where(c => c.UserName == "Name").Sum(c => (int?)c.Count) ?? 0;

Итак, корень проблемы в том, что запрос SQL выглядит так:

SELECT SUM([Votes].[Value])
FROM [dbo].[Votes] AS [Votes]
WHERE 1 = [Votes].[UserId] 

возвращает NULL

5 голосов
/ 30 марта 2009

Простой, но эффективный обходной путь заключается в суммировании голосов только при Point.Count> 0, поэтому у вас никогда не будет нулевых значений:

from i in Db.Items
select new VotedItem
{    
  ItemId = i.ItemId,
  Points = (from v in Db.Votes
            where b.ItemId == v.ItemId &&
            v.Points.Count > 0
            select v.Points).Sum()
}
4 голосов
/ 05 сентября 2013

Просто чтобы добавить другой метод в смесь:)

Where(q=> q.ItemId == b.ItemId && b.Points.HasValue).Sum(q=>q.Points.Value)

У меня был похожий сценарий, но я не сравнивал дополнительное поле при суммировании ...

Where(q => q.FinalValue.HasValue).Sum(q=>q.FinalValue.Value);
3 голосов
/ 22 октября 2014

Предполагая, что Очки - это Список Int32, как насчет чего-то вроде:

var sum = Points.DefaultIfEmpty().Sum(c => (Int32)c ?? 0)
2 голосов
/ 28 ноября 2012

Я думаю, что это тот же случай. Я решил это. Это мое решение:

var x = (from a in this.db.Pohybs
                 let sum = (from p in a.Pohybs
                            where p.PohybTyp.Vydej == true
                            select p.PocetJednotek).Sum()
                 where a.IDDil == IDDil && a.PohybTyp.Vydej == false
                 && ( ((int?)sum??0) < a.PocetJednotek)
                 select a);

Надеюсь, это поможет.

2 голосов
/ 04 апреля 2012

У меня была такая же проблема. Решено с пустым списком объединений:

List<int> emptyPoints = new List<int>() { 0 };

from i in Db.Items
select new VotedItem
{
 ItemId = i.ItemId,
 Points = (from v in Db.Votes
           where b.ItemId == v.ItemId
           select v.Points).Union(emptyPoints).Sum()
}

В случае, если "Points" является целым числом, это должно работать.

...