问题描述
我有一个 Things
的 Linq 集合,其中 Thing
有一个 Amount
(十进制)属性.
I have a Linq collection of Things
, where Thing
has an Amount
(decimal) property.
我正在尝试对某个特定的事物子集进行汇总:
I'm trying to do an aggregate on this for a certain subset of Things:
var total = myThings.Sum(t => t.Amount);
而且效果很好.但是后来我添加了一个条件,结果中没有任何东西:
and that works nicely. But then I added a condition that left me with no Things in the result:
var total = myThings.Where(t => t.OtherProperty == 123).Sum(t => t.Amount);
我得到一个错误,而不是得到 total = 0 或 null:
And instead of getting total = 0 or null, I get an error:
System.InvalidOperationException:无法将空值分配给一个 System.Decimal 类型的成员,它是一个不可为 null 的值类型.
System.InvalidOperationException: The null value cannot be assigned to a member with type System.Decimal which is a non-nullable value type.
这真的很讨厌,因为我没想到会出现这种行为.我本来希望 total 为零,也许为 null - 但肯定不会抛出异常!
That is really nasty, because I didn't expect that behavior. I would have expected total to be zero, maybe null - but certainly not to throw an exception!
我做错了什么?有什么解决方法/修复方法?
What am I doing wrong? What's the workaround/fix?
编辑 - 示例
感谢大家的评论.这是一些代码,复制并粘贴(未简化).它是 LinqToSql(也许这就是你无法重现我的问题的原因):
Thanks to all for your comments. Here's some code, copied and pasted (not simplified). It's LinqToSql (perhaps that's why you couldn't reproduce my problem):
var claims = Claim.Where(cl => cl.ID < 0);
var count = claims.Count(); // count=0
var sum = claims.Sum(cl => cl.ClaimedAmount); // throws exception
推荐答案
我可以使用以下针对 Northwind 的 LINQPad 查询重现您的问题:
I can reproduce your problem with the following LINQPad query against Northwind:
Employees.Where(e => e.EmployeeID == -999).Sum(e => e.EmployeeID)
这里有两个问题:
Sum()
被重载- LINQ to SQL 遵循 SQL 语义,而不是 C# 语义.
在 SQL 中,SUM(no rows)
返回 null
,而不是零.但是,查询的类型推断为您提供 decimal
作为类型参数,而不是 decimal?
.解决方法是帮助类型推断选择正确的类型,即:
In SQL, SUM(no rows)
returns null
, not zero. However, the type inference for your query gives you decimal
as the type parameter, instead of decimal?
. The fix is to help type inference select the correct type, i.e.:
Employees.Where(e => e.EmployeeID == -999).Sum(e => (int?)e.EmployeeID)
现在将使用正确的 Sum()
重载.
Now the correct Sum()
overload will be used.
这篇关于当可能存在空集时如何进行 Linq 聚合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!