Linq查询具有可空和

时间:2009-03-30 08:40:31

标签: c# linq linq-to-sql 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()
}

我收到了这个查询,但如果没有找到任何选票,则会失败:

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

我假设它是因为sum返回一个int而不是一个可空的int,给sum一个int?因为输入只会产生相同的错误,可能导致sum仅适用于整数。

对此有什么好的解决方法吗?

15 个答案:

答案 0 :(得分:73)

您想使用可以为空的Sum形式,因此请尝试将您的值转换为可为空的:

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

答案 1 :(得分:22)

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

答案 2 :(得分:19)

假设“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
}

答案 3 :(得分:11)

如果你不喜欢投射到nullabe十进制,你也可以尝试使用Linq To Objects和ToList()方法,

LinqToObjects空集合的总和为0,其中LinqToSql空集合的总和为空。

答案 4 :(得分:10)

尝试检查一下:

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 :(得分:5)

一个简单但有效的解决方法是仅将Points.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()
}

答案 6 :(得分:4)

只需在混音中添加另一种方法:)

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

我有类似的情况,但在总结时我还没有比较额外的字段......

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

答案 7 :(得分:3)

假设Points是Int32的列表,那么如下:

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

答案 8 :(得分:2)

我遇到了同样的问题。解决了空列表联合:

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”是整数,则应该有效。

答案 9 :(得分:2)

我认为这是同样的情况。 我解决了这是我的解决方案:

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

我希望这有帮助。

答案 10 :(得分:1)

可能是将此查询放入try / catch..if“exception”,然后找不到投票

答案 11 :(得分:0)

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

这样可行,但不是很漂亮或可读。

答案 12 :(得分:0)

我有一个类似的问题,并提出了解决方案,无法获得我想要从数据库中获取的任何内容,对这些数据进行计数,然后只有在我返回任何内容时才进行总结。由于某种原因无法让演员工作,所以如果其他人有类似的问题就发布这个。

e.g。

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

答案 13 :(得分:0)

与之前的答案类似,但您也可以将整个总和的结果转换为可空类型。

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
}

可以说这更符合实际情况,但它与this answer中的演员效果相同。

答案 14 :(得分:0)

以为我会抛出另一个解决方案。我遇到了类似的问题,这就是我最终解决问题的方法:

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