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

Posted

技术标签:

【中文标题】在表达式树中使用可为空的类型【英文标题】:Working with nullable types in Expression Trees 【发布时间】:2011-04-21 18:45:52 【问题描述】:

我有一个扩展方法可以使用字符串值动态过滤 Linq to Entities 结果。在我使用它来过滤可空列之前,它工作正常。这是我的代码:

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);

我是这样使用它的:

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

当我将它用于可空表列时,我遇到了一个异常:

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

我想不通。我该怎么办?

【问题讨论】:

Expression.GreaterThan fails if one operand is nullable type, other is non-nullable的可能重复 【参考方案1】:

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

Expression where = Expression.GreaterThanOrEqual(column, Expression.Convert(Expression.Constant(value), column.Type));

【讨论】:

我现在正在做这件事。我使用了Expression.Constant(value, column.Type),也就是说,我的情况有点复杂,因为我所有的过滤器值都是字符串(不是应该是可转换类型的对象:int -> int?、bool -> bool? 等)。所以我不仅需要动态创建表达式,还需要匹配列的类型中的过滤器值。 刚刚改回了我之前抛出此错误的代码。使用Expression.Convert 比处理检查类型是否为 Nullable(使用反射)要容易得多,如果是,则使用显式创建的 Nullable&lt;&gt; 创建表达式(作为我的辅助方法的返回)。我只是将字符串转换为所需的值类型(int、bool 等),然后是Expression.Convert(Expression.Constant(castValue), columnType)。繁荣。感谢您的发现! @JoeBrockhaus 为什么不直接使用带有Expresson.Constant 的类型,不管它是否可以为空?确实,这也是我在这里推荐的答案。 爱你,这帮助很大【参考方案2】:

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

例如

Expression.Constant(value, column.Type)

【讨论】:

这是一个绝妙的解决方案【参考方案3】:

您可以通过以下方式检查一个类型是否可以为空: if (typeof(T).Equals(typeof(Nullable)) 我相信然后继续进行特殊处理。如果您可以以某种方式调用 GetValueOrDefault() 方法,这将起作用,或者以编程方式将比较值创建为相同类型。

HTH。

【讨论】:

以上是关于在表达式树中使用可为空的类型的主要内容,如果未能解决你的问题,请参考以下文章

中继/ graphql:可为空的响应或捕获查询错误的方法

.NET 使用可为空的引用类型实现 IEnumerator

如何使用 System.Text.Json 处理可为空的引用类型?

为啥条件运算符不能正确地允许使用“null”来分配给可为空的类型? [复制]

asp.net lamda查询表达式判断Guid的值是不是为空

堆栈溢出错误可为空的数字类型c#