我有这段代码(好吧,我没有,但类似的东西:p)
var dogs = Dogs.Select(ø => new Row
{
Name = ø.Name,
WeightOfNiceCats = ø.Owner
.Cats
.Where(æ => !æ.Annoying)
.Sum(æ => æ.Weight),
});
在这里,我通过所有的狗,并总结所有不讨厌的猫的重量(成为一个不可空的小数)与猫拥有相同的所有者。当然,几乎所有的猫都很烦,所以我得到了这个错误:
无法将null值分配给System.Decimal类型的成员,该类型是不可为空的值类型。
使用的字段或外键都不能为空。因此,当Where
子句不返回猫时会发生错误。但是我该如何解决这个问题呢?当发生这种情况时,我希望它返回0。在DefaultIfEmpty()
子句后尝试Where
,但后来我收到此错误:
对象引用未设置为对象的实例。
我猜这是可以理解的。我尝试在??
之后添加Sum
,但由于此错误,它不会编译:
运营商'??'不能应用于'decimal'和'decimal'类型的操作数
当然这也是有道理的。那我该怎么办?如果Sum
只是在没有任何要求的情况下返回0,那将会很好。或某种SumOrZero
语句。制作一个与Linq2SQL一起使用的SumOrZero
方法会不会很难?
答案 0 :(得分:21)
这就是我现在最终的结果:
.Sum(æ => (decimal?) æ.Weight) ?? 0.0M,
这就像一个魅力。
我仍然希望有一个SumOrZero
我可以使用,这与常规Sum
完全相同,但它不会因任何原因返回null
。就像其他人已经注意到的那样,这对于IEnumerable
来说非常容易,但是为IQueryable
创建它会更加狡猾,所以它可以与Linq2SQL等一起使用。所以我将它留在那里现在。虽然如果某人有一天感到无聊并为SumOrZero
写了一个IQueryable
,它与Linq2SQL一起用于所有数字类型,请告诉我:D
答案 1 :(得分:5)
在LINQ to Objects中它很容易。使用LINQ to SQL会更难。您可以编写自己的扩展方法,该方法使用从普通表达式构建的表达式调用Queryable.Sum
,并使用强制转换为可空类型。我怀疑你需要这样做?但是在调用代码中为0m。换句话说,你可以这样做:
.SumOrNull(æ => æ.Weight) ?? 0M,
.SumOrNull的签名为:
public static decimal? SumOrNull<TSource, decimal>(this IQueryable<TSource>,
Func<TSource,decimal> projection)
你基本上可以为Queryable支持的所有值类型编写。你可以一般地写它,并使用反射在Queryable中调用适当的方法,但这也会很蹩脚。
说实话,我觉得你最擅长的是你。
答案 2 :(得分:3)
你已经给出的技巧(.Sum(æ => (decimal?) æ.Weight) ?? 0.0M
)是关于这个场景在数据库中作为查询执行时所能想到的最好的技巧。有点烦人,但还有更糟糕的事情......
与LINQ-to-Objects不同,您不能只添加自己的扩展方法,因为它需要由底层提供程序映射。
答案 3 :(得分:0)
你想使用DefaultIfEmpty,它将返回一个单元素为0的IEnumberable,并且在语义上与你需要的相同。
由于你有一个可以为空的十进制数,你可能不得不使用方法的第二个版本来获取2个参数。