Entity Framework 查询中的 Sum() Returns null

Sum() Returns null in Entity Framework Query

我有一个包含这些行的大 Entity Framework 查询。

var programs = from p in Repository.Query<Program>()
               where p.OfficeId == CurrentOffice.Id
               let totalCharges = p.ProgramBillings.Where(b => b.Amount > 0 && b.DeletedDate == null).Select(b => b.Amount).Sum()
               let totalCredits = p.ProgramBillings.Where(b => b.Amount < 0 && b.DeletedDate == null).Select(b => -b.Amount).Sum()
               let billingBalance = (totalCharges - totalCredits)

当我具体化数据时,出现以下错误:

The cast to value type 'Decimal' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

如果我按如下方式更改我的查询(添加到两个类型转换中),错误就会消失。

var programs = from p in Repository.Query<Program>()
               where p.OfficeId == CurrentOffice.Id
               let totalCharges = (decimal?)p.ProgramBillings.Where(b => b.Amount > 0 && b.DeletedDate == null).Select(b => b.Amount).Sum()
               let totalCredits = (decimal?)p.ProgramBillings.Where(b => b.Amount < 0 && b.DeletedDate == null).Select(b => -b.Amount).Sum()
               let billingBalance = (totalCharges - totalCredits)

我不明白这个。 ProgramBilling.Amount 是一个不可为 null 的小数。如果我将鼠标悬停在 Sum() 调用上,Intellisense 会提示它 returns 输入 Decimal。然而,其他测试证实,在我的第二个版本中,totalChargestotalCredits 对于 ProgramBillings 没有数据的那些行都设置为 null。

问题:

  1. 我了解 Sum() 返回 0 表示空集合。在什么情况下不是这样?

  2. 如果有时情况并非如此,那为什么当我将鼠标悬停在 Sum() 上时,Intellisense 显示它 returns 键入 Decimal 而不是 Decimal?看来 Intellisense 的理解和我一样。

编辑:

似乎一个简单的解决方法是执行类似 Sum() ?? 0m 的操作。但这是非法的,给我错误:

Operator '??' cannot be applied to operands of type 'decimal' and 'decimal'

I understood Sum() returned 0 for an empty collection. Under what circumstances is this not true?

当您不使用 LINQ to objects 时,就像这里的情况一样。这里有一个查询提供程序正在将此查询转换为 SQL。 SQL 操作的 SUM 运算符具有不同的语义。

And if sometimes that is not true, then why when I hover over Sum(), Intellisense shows it returns type Decimal and not Decimal? It appears Intellisense had the same understanding that I had.

C# LINQ SUM 运算符不return 可为空的值;它需要有一个非空值,但是 SQL SUM 运算符有不同的语义,它 returns null 对空集求和时,而不是 0null 值是在 C# 需要非空值的上下文中提供的,这是一切都崩溃的全部原因。如果此处的 C# LINQ SUM 运算符 returned 一个可为 null 的值,则 null 可以毫无问题地 returned。

C# 运算符和它用来表示的 SQL 运算符之间的差异导致了此错误。

当集合为空时,我在我的一个 EF 查询中遇到了同样的问题,一个快速解决方法是转换为可为 null 的十进制:

var total = db.PaiementSet.Sum(o => (Decimal?)o.amount) ?? 0M;

希望对您有所帮助。

在 .Sum 之前添加一个 DefaultIfEmpty(0.0M)