Запрос Linq с нулевой суммой


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, давая sum a int? поскольку входные данные дают только ту же ошибку, вероятно, причина sum работает только на ints.

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

15 65

15 ответов:

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() 
}

EDIT-ok как насчет этого... (Снова стреляю, так как я не знаю вашу модель...):

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) 
}

вы хотите использовать nullable форму 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

предполагая, что "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
}

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

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

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

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

простой, но эффективный обходной путь будет заключаться только в суммировании голосов, Где очки.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()
}

просто добавить еще один метод в микс:)

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

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

Where(q => q.FinalValue.HasValue).Sum(q=>q.FinalValue.Value);

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

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()
}

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

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

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);

Я надеюсь, что это поможет.

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

var sum = Points.DefaultIfEmpty().Sum(c => (Int32)c ?? 0)

может быть, чтобы поместить этот запрос в try / catch..если "исключение", то голосов не нашлось

        (from i in Db.Items
         where (from v in Db.Votes
                where i.ItemId == v.ItemId
                select v.Points).Count() > 0
         select new VotedItem
         {
             ItemId = i.ItemId,
             Points = (from v in Db.Items
                       where i.ItemId == v.ItemId
                       select v.Points).Sum()
         }).Union(from i in Db.Items
                  where (from v in Db.Votes
                         where i.ItemId == v.ItemId
                         select v.Points).Count() == 0
                  select new VotedItem
                  {
                      ItemId = i.ItemId,
                      Points = 0
                  }).OrderBy(i => i.Points);

это работает, но не очень красиво или читабельно.

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

например

Votes = (from v in Db.Votes
          where b.ItemId = v.ItemId
          select v)

а затем проверить, если у вас есть какие-либо результаты, так что вы не получите null возвращается.

If (Votes.Count > 0) Then
    Points = Votes.Sum(Function(v) v.Points)
End If

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

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

возможно, это лучше соответствует тому, что происходит на самом деле, но это имеет тот же эффект, что и бросок в ответ.

думал, что я бы бросил другое решение там. У меня была аналогичная проблема, и вот как я ее решил:

Where(a => a.ItemId == b.ItemId && !b.IsPointsNull()).Sum(b => b.Points)