18

我有这个代码(好吧,我没有,但是类似的东西:p)

    var dogs = Dogs.Select(ø => new Row
    {
            Name = ø.Name,
            WeightOfNiceCats = ø.Owner
              .Cats
              .Where(æ => !æ.Annoying)
              .Sum(æ => æ.Weight),
    });

在这里,我遍历所有狗并总结所有与狗拥有相同主人的不烦人的猫的重量(成一个不可为空的小数)。当然,几乎所有的猫都很烦人,所以我得到了这个错误:

不能将 null 值分配给 System.Decimal 类型的成员,该类型是不可为 null 的值类型。

使用的任何字段或外键都不能为空。因此,当Where子句不返回猫时,就会发生错误,而这通常会发生。但是我该如何解决呢?我希望它在发生这种情况时返回 0。尝试使用DefaultIfEmpty()afterWhere子句,但随后出现此错误:

你调用的对象是空的。

我想这是可以理解的。我尝试在??之后添加一个Sum,但由于此错误,它不会编译:

操作员 '??' 不能应用于“十进制”和“十进制”类型的操作数

这当然也是有道理的。那么我能做什么呢?Sum如果在没有什么可总结的情况下,事情只是返回 0,那就太好了。或者某种SumOrZero声明。SumOrZero制作一种适用于 Linq2SQL的方法会很困难吗?

4

4 回答 4

22

这就是我现在的结果:

.Sum(æ => (decimal?) æ.Weight) ?? 0.0M,

这就像一个魅力。

我仍然希望有一个SumOrZero我可以使用的,它的工作方式与普通的完全一样,Sum只是它永远不会null因任何原因返回。就像其他人所指出的那样,这很容易制作,IEnumerable但创建起来有点麻烦,IQueryable因此它可以与 Linq2SQL 等一起使用。所以我现在就把它留在那里。虽然如果有人有一天感到无聊并写了一个SumOrZero适用IQueryable于所有数字类型的 Linq2SQL,请告诉我:D

于 2009-02-23T12:57:32.253 回答
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 中调用适当的方法,但这也很麻烦。

老实说,我认为你最好用你所拥有的。

于 2009-02-23T09:29:25.060 回答
3

您已经给出的技巧.Sum(æ => (decimal?) æ.Weight) ?? 0.0M(有点烦人,但还有更糟糕的事情......

与 LINQ-to-Objects 不同,您不能只添加自己的扩展方法,因为它需要由底层提供程序映射。

于 2009-02-23T09:23:28.057 回答
0

您想使用 DefaultIfEmpty,它将返回一个带有单个元素 0 的 IEnumberable,这在语义上与您的要求相同。

由于您有一个可为空的小数,您可能必须使用采用 2 个参数的方法的第二个版本。

于 2009-02-23T09:37:32.950 回答