具有可空和的 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 一个 int?由于输入只给出相同的错误,可能导致 sum 只对 int 起作用。

有什么好的解决办法吗?

69978 次浏览
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)
}

一个简单但有效的解决办法就是只把得分加起来。Count > 0,因此您永远不会有 null 值:

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

这个可以,但是不是很漂亮或者可读。

您希望使用可为空的 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

如果你不喜欢转换为空小数,你也可以尝试使用 Linq To Objects with ToList ()方法,

空集合的 LinqToObjects Sum 为0,其中空集合的 LinqToSql Sum 为 null。

假设“ v 点”是一个小数,只需使用以下内容:

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
}

我也有同样的问题,用空列表联合解决了:

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

如果“积分”是整数,这应该可以。

我也遇到过类似的问题,所以我想出了一个解决方案,不管我想从数据库中得到什么,都要计算一下,然后只有当我得到任何返回值的时候,才做一个求和运算。因为某些原因无法让演员们工作,所以如果其他人也有类似的问题,就发布这个。

例如:。

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

看看这个:

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

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

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
}

可以说,这更符合什么是真正发生了什么,但它有同样的效果,作为在 这个答案演员。

我觉得这是同一个案子。 我解决了,这是我的解决办法:

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

希望这个能帮上忙。

只需要在混合中添加另一个方法:)

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

我有一个类似的场景,但我没有比较一个额外的字段,当总结..。

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

我觉得我应该提出另一个解决方案。我也遇到过类似的问题,我就是这样解决它的:

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

假设 Point 是一个 Int32列表,那么这样的东西怎么样:

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