在表达式树中使用可空类型

dst*_*str 31 c# linq lambda entity-framework expression-trees

我有一个扩展方法,使用字符串值动态过滤Linq到实体结果.它工作正常,直到我用它来过滤可空列.这是我的代码:

public static IOrderedQueryable<T> OrderingHelperWhere<T>(this IQueryable<T> source, string columnName, object value)
{
    ParameterExpression table = Expression.Parameter(typeof(T), "");
    Expression column = Expression.PropertyOrField(table, columnName);
    Expression where = Expression.GreaterThanOrEqual(column, Expression.Constant(value));
    Expression lambda = Expression.Lambda(where, new ParameterExpression[] { table });

    Type[] exprArgTypes = { source.ElementType };

    MethodCallExpression methodCall = Expression.Call(typeof(Queryable), 
                                                      "Where", 
                                                      exprArgTypes, 
                                                      source.Expression, 
                                                      lambda);

    return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(methodCall);
}
Run Code Online (Sandbox Code Playgroud)

这是我如何使用它:

var results = (from row in ctx.MyTable select row)
              .OrderingHelperWhere("userId", 5);//userId is nullable column
Run Code Online (Sandbox Code Playgroud)

这是我在将可用于可空表列时使用的异常:

没有为类型'System.Nullable`1 [System.Int32]'和'System.Int32'定义二元运算符GreaterThanOrEqual

我无法理解这一点.我该怎么办?

dst*_*str 55

我必须使用Expression.Convert将值类型转换为列类型:

Expression where = Expression.GreaterThanOrEqual(column, Expression.Convert(Expression.Constant(value), column.Type));
Run Code Online (Sandbox Code Playgroud)

  • 刚刚改回了之前引发此错误的代码。使用“Expression.Convert”比处理检查类型是否为 Nullable(使用反射)以及如果是的话使用显式创建的“Nullable&lt;&gt;”创建表达式(作为我的辅助方法的返回)要容易得多。我只需将字符串转换为所需的值类型(int、bool 等),然后转换为“Expression.Convert(Expression.Constant(castValue), columnType)”。繁荣。感谢这个发现! (2认同)
  • @JoeBrockhaus 为什么不只使用带有 `Expresson.Constant` 的类型,无论它是否可为空?事实上,这也是我在这里推荐的答案。 (2认同)

小智 6

类型可以作为第二个参数传递给Expression.Constant 函数像typeof(int?)之类的东西,或者在这个问题的情况下,是 column.Type

例如

Expression.Constant(value, column.Type)
Run Code Online (Sandbox Code Playgroud)