当可能存在空集时如何进行 Linq 聚合?

How to do Linq aggregates when there might be an empty set?(当可能存在空集时如何进行 Linq 聚合?)
本文介绍了当可能存在空集时如何进行 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)

这里有两个问题:

  1. Sum() 被重载
  2. 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 聚合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

Is Unpivot (Not Pivot) functionality available in Linq to SQL? How?(Linq to SQL 中是否提供 Unpivot(非 Pivot)功能?如何?)
How to know if a field is numeric in Linq To SQL(如何在 Linq To SQL 中知道字段是否为数字)
Linq2SQl eager load with multiple DataLoadOptions(具有多个 DataLoadOptions 的 Linq2SQl 急切加载)
Extract sql query from LINQ expressions(从 LINQ 表达式中提取 sql 查询)
LINQ Where in collection clause(LINQ Where in collection 子句)
Orderby() not ordering numbers correctly c#(Orderby() 没有正确排序数字 c#)