我有一个包含这些行的大型实体框架查询。
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)
当我实现数据时,我收到以下错误:
转换为值类型'Decimal'失败,因为具体化值为null。结果类型的泛型参数或查询必须使用可空类型。
如果我按如下方式更改我的查询(在两个类型转换中添加),则错误消失。
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
是一个不可为空的十进制数。如果我将鼠标悬停在Sum()
调用上,Intellisense会说它返回Decimal类型。然而,其他测试证实,在我的第二个版本中,totalCharges
和totalCredits
对ProgramBillings
没有数据的行都设置为空。
问题:
我理解Sum()
为空集合返回0。在什么情况下这不是真的?
如果有时这不是真的,那么为什么当我将鼠标悬停在Sum()
上时,Intellisense会显示它返回的类型为Decimal而不是Decimal?看来Intellisense和我有同样的理解。
修改
似乎可以轻松解决Sum() ?? 0m
之类的问题。但这是非法的,给我错误:
运营商'??'不能应用于'decimal'和'decimal'类型的操作数
答案 0 :(得分:10)
我理解Sum()为空集合返回0。在什么情况下这不是真的?
当您不使用LINQ对象时,就像这里的情况一样。这里有一个查询提供程序,可以将此查询转换为SQL。 SQL操作对其SUM运算符具有不同的语义。
如果有时候这不是真的,那么为什么当我将鼠标悬停在Sum()上时,Intellisense会显示它返回的类型为Decimal而不是Decimal?似乎Intellisense和我有同样的理解。
C#LINQ SUM运算符不返回可为空的值;它需要具有非空值,但SQL SUM运算符具有不同的语义,它在对空集求和而不是null
时返回0
。在C#需要非空值的上下文中提供null
值的事实是一切都在破坏的全部原因。如果此处的C#LINQ SUM运算符返回了可以为空的值,则可以只返回null
而没有任何问题。
C#运算符与用于表示导致此错误的SQL运算符之间存在差异。
答案 1 :(得分:2)
当我的一个EF查询中,当集合为空时,我遇到了同样的问题,一个快速解决方法是强制转换为可为空的十进制:
db.data.aggregate([
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$value.count", 0 ] },
{ "$mod": [
{ "$subtract": [ "$value.count", 0 ] },
5
]}
]
},
"count": { "$sum": 1 }
}}
])
希望它有所帮助。
答案 2 :(得分:0)
在.Sum之前添加一个DefaultIfEmpty(0.0M)