在表达式树中使用可为空的类型
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<>
创建表达式(作为我的辅助方法的返回)。我只是将字符串转换为所需的值类型(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。
【讨论】:
以上是关于在表达式树中使用可为空的类型的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 System.Text.Json 处理可为空的引用类型?
为啥条件运算符不能正确地允许使用“null”来分配给可为空的类型? [复制]