动态lambda表达式(OrderBy)和可空属性类型
本文关键字:属性 类型 lambda 表达式 OrderBy 动态 | 更新日期: 2023-09-27 18:08:56
我试图动态创建将通过实体框架从数据库排序数据的表达式。但我遇到了一个无法克服的问题。也许让我解释一下我在做什么。我的目标是创建这样的表达式:
x => x.Property
其中"Property"是我想动态指定的属性名
现在,让我们转到类,它表示数据库中的表(我简化了它,使事情更清楚):
public class MyModelClass
{
public long MyLongProperty { get; set; }
public decimal? MyNullableDecimalProperty { get; set; } // IMPORTANT: it's nullable
}
这是我的代码,我试图创建前面描述的表达式:
// Db is EntityFramework context
IQueryable<MyModelClass> list = Db.MyModels.Select(x => x);
// x =>
var argument = Expression.Parameter(list.ElementType, "x");
// x.MyNullableDecimalProperty
var propertyToOrder = Expression.Property(argument, "MyNullableDecimalProperty");
// x => x.MyNullableDecimalProperty
var finalExpression = Expression.Call(
typeof (Queryable),
"OrderBy",
new[] { list.ElementType, typeof(IComparable) },
list.Expression,
Expression.Lambda<Func<MyModelClass, IComparable>>(propertyToOrder, argument));
list = list.Provider.CreateQuery<MyModelClass>(finalExpression);
第4条语句出现问题(var finalExpression = Expression.Call(…))。我得到一个异常:
类型为" System. nullable "的表达式不能用于返回类型" System.IComparable "
据我所知,问题是我使用"IComparable"类型,其中"MyNullableDecimalProperty"是空的,空的不用户IComparable接口。当我通过"MyLongProperty"排序或替换"IComparable"时,不会抛出异常。
我的问题是:
我应该使用什么类型来使它与任何可空属性一起工作?
是否可能使用一种类型,它将适用于所有属性,无论它们是可空的还是不可空的
注意:我知道我可以使用动态Linq库,但我对这个解决方案不感兴趣-我想学习如何在不使用第三方库的情况下克服它。
没有理由使用IComparable
。实际上,许多类似的类型都没有实现IComparable
。只要使用你要传递的运行时类型:
var finalExpression = Expression.Call(
typeof (Queryable),
"OrderBy",
new[] { list.ElementType, propertyToOrder.Type },
list.Expression,
Expression.Lambda(propertyToOrder, new [] { argument }));
您不需要指定IComparable部分,您也可以使用Queryable。OrderBy/orderby降序方法来帮助你:
IQueryable<TSource> source = .....
var sourceType = typeof(TSource);
var parameter = Expression.Parameter(sourceType, "item");
var propertyInfo = GetProperty(sourceType, propertyName);
var orderByProperty = Expression.Property(parameter, propertyInfo);
orderBy = Expression.Lambda(orderByProperty, new[] { parameter });
return Queryable.OrderBy(source, (dynamic)orderBy)
试一试,看看效果如何,我很确定这对原生类型和可空类型都有效。