Sum()在Entity Framework Query中返回null

时间:2015-01-09 18:29:32

标签: c# linq 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)

当我实现数据时,我收到以下错误:

  

转换为值类型'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类型。然而,其他测试证实,在我的第二个版本中,totalChargestotalCreditsProgramBillings没有数据的行都设置为空。

问题:

  1. 我理解Sum()为空集合返回0。在什么情况下这不是真的?

  2. 如果有时这不是真的,那么为什么当我将鼠标悬停在Sum()上时,Intellisense会显示它返回的类型为Decimal而不是Decimal?看来Intellisense和我有同样的理解。

  3. 修改

    似乎可以轻松解决Sum() ?? 0m之类的问题。但这是非法的,给我错误:

      

    运营商'??'不能应用于'decimal'和'decimal'类型的操作数

3 个答案:

答案 0 :(得分:10)

  

我理解Sum()为空集合返回0。在什么情况下这不是真的?

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

  

如果有时候这不是真的,那么为什么当我将鼠标悬停在Sum()上时,Intellisense会显示它返回的类型为Decimal而不是Decimal?似乎Intellisense和我有同样的理解。

C#LINQ SUM运算符不返回可为空的值;它需要具有非空值,但S​​QL 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)