How to do Linq aggregates when there might be an empty set?(当可能存在空集时如何进行 Linq 聚合?)
问题描述
我有一个 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 聚合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:当可能存在空集时如何进行 Linq 聚合?
				
        
 
            
        - Azure Active Directory 与 MVC,客户端和资源标识同一 2022-01-01
 - 为什么 C# 中的堆栈大小正好是 1 MB? 2022-01-01
 - 在 LINQ to SQL 中使用 contains() 2022-01-01
 - 在 C# 中异步处理项目队列 2022-01-01
 - CanBeNull和ReSharper-将其用于异步任务? 2022-01-01
 - 使用 rss + c# 2022-01-01
 - C# 通过连接字符串检索正确的 DbConnection 对象 2022-01-01
 - 带问号的 nvarchar 列结果 2022-01-01
 - Windows 喜欢在 LINUX 中使用 MONO 进行服务开发? 2022-01-01
 - 是否可以在 .Net 3.5 中进行通用控件? 2022-01-01
 
						
						
						
						
						