当可能存在空集时如何进行 Linq 聚合?
- 作者: 怪我咯45804273
- 来源: 51数据库
- 2022-12-08
问题描述
我有一个 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.
- C#通过fleck实现wss协议的WebSocket多人Web实时聊天(附源码)
- 团队城市未满足要求:MSBuildTools12.0_x86_Path 存在
- 使用 MSBuild.exe 在发布模式下构建 C# 解决方案
- 当我发布 Web 应用程序时,AfterPublish 脚本不运行
- 构建时 T4 转换的产品仅在下一个构建中使用
- ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json
- 新的 .csproj 格式 - 如何将整个目录指定为“链接文件"到子目录?
- 如何将条件编译符号(DefineConstants)传递给 msbuild
- MSBuild 支持 Visual Studio 2017 RTM 中的 T4 模板
- NuGet 包还原找不到包,没有源
