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 聚合?
基础教程推荐
- 首先创建代码,多对多,关联表中的附加字段 2022-01-01
- 经典 Asp 中的 ResolveUrl/Url.Content 等效项 2022-01-01
- 将事件 TextChanged 分配给表单中的所有文本框 2022-01-01
- 从 VS 2017 .NET Core 项目的发布目录中排除文件 2022-01-01
- 错误“此流不支持搜索操作"在 C# 中 2022-01-01
- 是否可以在 asp classic 和 asp.net 之间共享会话状态 2022-01-01
- 全局 ASAX - 获取服务器名称 2022-01-01
- JSON.NET 中基于属性的类型解析 2022-01-01
- 在 VS2010 中的 Post Build 事件中将 bin 文件复制到物 2022-01-01
- 如何动态获取文本框中datagridview列的总和 2022-01-01
