Linq查询具有可空和

And*_*asN 69 c# linq nullable sum linq-to-sql

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()
}
Run Code Online (Sandbox Code Playgroud)

我得到了这个查询,但是如果没有找到异常的投票则它会失败:

The null value cannot be assigned to a member with type System.Int32 which is a non-nullable value type.
Run Code Online (Sandbox Code Playgroud)

我假设它因为sum返回一个int而不是一个可空的int,给一个int一个?作为输入只给出相同的错误,可能导致sum仅适用于int.

有什么好的解决方法吗?

Sco*_*ord 74

您想要使用可以为空的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)
}
Run Code Online (Sandbox Code Playgroud)

这里将更详细地讨论您的问题:

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


Ras*_*ack 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() 
}
Run Code Online (Sandbox Code Playgroud)

编辑 - 好吧这个...(由于我不知道你的模型,再次拍摄......):

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) 
}
Run Code Online (Sandbox Code Playgroud)


小智 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
}
Run Code Online (Sandbox Code Playgroud)


Emi*_*mir 11

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

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


Pav*_*nik 10

试着看看这个:

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

所以,问题的根源是SQL查询,如下所示:

SELECT SUM([Votes].[Value])
FROM [dbo].[Votes] AS [Votes]
WHERE 1 = [Votes].[UserId] 
Run Code Online (Sandbox Code Playgroud)

返回NULL


Raz*_*zie 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()
}
Run Code Online (Sandbox Code Playgroud)