C# 动态lambda表达式(OrderBy)和可为空的属性类型
我试图动态创建表达式,通过实体框架对数据库中的数据进行排序。但我遇到了一个问题,无法克服它。也许让我解释一下我想做什么。我的目标是创建如下表达式:C# 动态lambda表达式(OrderBy)和可为空的属性类型,c#,linq,entity-framework,lambda,expression-trees,C#,Linq,Entity Framework,Lambda,Expression Trees,我试图动态创建表达式,通过实体框架对数据库中的数据进行排序。但我遇到了一个问题,无法克服它。也许让我解释一下我想做什么。我的目标是创建如下表达式: x => x.Property 其中“Property”是我要动态指定的属性的名称 现在,让我们转到类,它表示数据库中的表(我简化了它以使事情更清楚): 这是我的代码,我正在尝试创建前面描述的表达式: // Db is EntityFramework context IQueryable<MyModelClass> list =
x => x.Property
其中“Property”是我要动态指定的属性的名称
现在,让我们转到类,它表示数据库中的表(我简化了它以使事情更清楚):
这是我的代码,我正在尝试创建前面描述的表达式:
// 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);
//数据库是EntityFramework上下文
IQueryable list=Db.MyModels.Select(x=>x);
//x=>
var参数=Expression.Parameter(list.ElementType,“x”);
//x.MyNullableDecimalProperty
var propertyToOrder=Expression.Property(参数“MyNullableDecimalProperty”);
//x=>x.MyNullableDecimalProperty
var finalExpression=Expression.Call(
类型(可查询),
“订购人”,
新[]{list.ElementType,typeof(IComparable)},
列表。表达式,
Lambda(propertyToOrder,argument));
list=list.Provider.CreateQuery(finalExpression);
问题出现在第4条语句(var finalExpression=Expression.Call(…)中)。我得到一个例外:
“System.Nullable`1[System.Decimal]”类型的表达式不能用于返回类型“System.IComparable”
据我所知,问题在于我使用“IComparable”类型,其中“MyNullableDecimalProperty”可为null,而Nullable不使用IComparable接口。当我按“MyLongProperty”排序或替换“IComparable”时,不会引发异常
所以我的问题是:
注意:我知道我可以使用ex.Dynamic Linq库,但我对这个解决方案不感兴趣-我想学习如何在不使用第三方库的情况下克服它。您不需要指定IComparable部分,也可以使用Queryable.OrderBy/OrderByDescending方法来帮助您:
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)
IQueryable源=。。。。。
var sourceType=typeof(TSource);
var参数=Expression.parameter(sourceType,“item”);
var propertyInfo=GetProperty(sourceType,propertyName);
var orderByProperty=Expression.Property(参数,propertyInfo);
orderBy=Expression.Lambda(orderByProperty,新[]{parameter});
返回Queryable.OrderBy(源,(动态)OrderBy)
试一试,看看进展如何,我很确定这对本机类型和可空类型都有效。没有理由使用
IComparable
。事实上,许多可比较的类型没有实现IComparable
。只需使用所传递内容的运行时类型:
var finalExpression = Expression.Call(
typeof (Queryable),
"OrderBy",
new[] { list.ElementType, propertyToOrder.Type },
list.Expression,
Expression.Lambda(propertyToOrder, new [] { argument }));
如果为
MyModelClass
实现IComperable
,或者将MyNullableDecimalProperty
封装到实现IComperable
的类中,该怎么办。
var finalExpression = Expression.Call(
typeof (Queryable),
"OrderBy",
new[] { list.ElementType, propertyToOrder.Type },
list.Expression,
Expression.Lambda(propertyToOrder, new [] { argument }));