Queryable.Aggregate不使用空值

时间:2017-03-09 13:59:02

标签: c# .net linq iqueryable linq-expressions

我正在撰写一个转化IQueryable查询的访问者。它使用种子Aggregate的{​​{1}}方法,然后使用一些func对其进行转换。我的问题是这个null是null类型。但我得到了一个例外

decimal?

经过一些研究后,我发现它本身就是'Expression of type 'System.Object' cannot be used for parameter of type 'System.Nullable`1[System.Decimal]' of method 'System.Nullable`1[System.Decimal] Aggregate[Nullable`1,Nullable`1] (System.Linq.IQueryable`1[System.Nullable`1[System.Decimal]], System.Nullable`1[System.Decimal], System.Linq.Expressions.Expression`1[System.Func`3[System.Nullable`1[System.Decimal], System.Nullable`1[System.Decimal],System.Nullable`1[System.Decimal]]])'' ,这会破坏我的查询:

Aggregate

我的问题是public static TAccumulate Aggregate<TSource,TAccumulate>(this IQueryable<TSource> source, TAccumulate seed, Expression<Func<TAccumulate,TSource,TAccumulate>> func) { if (source == null) throw Error.ArgumentNull("source"); if (func == null) throw Error.ArgumentNull("func"); return source.Provider.Execute<TAccumulate>( Expression.Call( null, GetMethodInfo(Queryable.Aggregate, source, seed, func), new Expression[] { source.Expression, Expression.Constant(seed), Expression.Quote(func) } )); } Expression.Constant(seed)null将其转换为类型对象的常量:

Expression.Constant

因此我的public static ConstantExpression Constant(object value) { return ConstantExpression.Make(value, value == null ? typeof(object) : value.GetType()); } 转换为new decimal?(),我收到此错误。

这有什么解决方法吗?似乎不可能在.net框架中修复(即使它可能,它将在4.7或更高版本中修复)。我会为此创建一个拉取请求,但我确信它不会被接受。

要重现的代码段:

(object) null

2 个答案:

答案 0 :(得分:3)

从代码片段开始重现

var result2 = new int?[] {1}.AsQueryable().DefaultIfEmpty().Aggregate((a, b) => b);

我将其更改为

var result3 = new int?[0].AsQueryable().DefaultIfEmpty().Aggregate(
   (a, b) => a.GetValueOrDefault() + b.GetValueOrDefault());

如果你想要一笔总和

空集合

var result4 = new int?[]{1,2,null}.AsQueryable().DefaultIfEmpty().Aggregate(
 (a, b) => a.GetValueOrDefault() + b.GetValueOrDefault());

包含null

DefaultIfEmpty().Aggregate

基本上,我建议使用{{1}}

答案 1 :(得分:0)

这个怎么样:

public static TAccumulate Aggregate<TSource,TAccumulate>(this IQueryable<TSource> source, TAccumulate seed, Expression<Func<TAccumulate,TSource,TAccumulate>> func) {
    if (source == null)
        throw Error.ArgumentNull("source");
    if (func == null)
        throw Error.ArgumentNull("func");
    return source.Provider.Execute<TAccumulate>(
        Expression.Call(
            null,
            GetMethodInfo(Queryable.Aggregate, source, seed, func),
            new Expression[] { source.Expression, Expression.Constant(seed, typeof(TAccumulate)), Expression.Quote(func) }
            ));
}