LINQ to Entities OrderBy 表达式树
Posted
技术标签:
【中文标题】LINQ to Entities OrderBy 表达式树【英文标题】:LINQ to Entities OrderBy Expression Tree 【发布时间】:2016-04-17 18:19:17 【问题描述】:我正在尝试编写一个 LINQ 查询来 orderBy 由字符串值给出的动态属性。
这是我的原始代码:
Expression<Func<T, dynamic>> orderBy = i => i.GetType().GetProperty("PropertyName").GetValue(null);
当我尝试运行此 orderBy 时,出现以下异常:
LINQ to Entities 无法识别该方法 'System.Object GetValue(System.Object)' 方法,该方法不能 被翻译成商店表达式。
我试图通过创建一个表达式树来解决这个问题,它会给我相同的结果。代码应该能够根据参数返回任何类型,但我遇到了返回类型的问题。如果我不转换值,我会得到一个不同的错误,说 w Nullable DateTime 不能转换为 Object。这是我到目前为止的代码:
ParameterExpression pe = Expression.Parameter(typeof(T), "s");
Expression<Func<T, dynamic>> orderByExpression = Expression.Lambda<Func<T, dynamic>>(Expression.Convert(Expression.Property(pe, "PropertyName"), typeof(object)), pe);
还有我的新例外:
无法转换类型 'System.Nullable`1[[System.DateTime]]' 输入 '系统.对象'。 LINQ to Entities 仅支持转换 EDM 原语 或枚举类型。
如何编写这个表达式树来返回动态类型?还有我应该在 LINQ 中执行此操作的更好方法吗?
【问题讨论】:
看看get property of inner object 看看Marc Gravells Dynamic OrderBy 【参考方案1】:Expression<Func<T, TT>>
没有模板参数,它允许您表示引用类型和值类型。当然,您可以构建表达式,但您必须通过反射与它们进行交互。
这将正确地对集合进行排序:
IOrderedEnumerable<TEntityType> SortMeDynamically<TEntityType>(IEnumerable<TEntityType> query, string propertyname)
var param = Expression.Parameter(typeof(TEntityType), "s");
var prop = Expression.PropertyOrField(param, propertyname);
var sortLambda = Expression.Lambda(prop, param);
Expression<Func<IOrderedEnumerable<TEntityType>>> sortMethod = (() => query.OrderBy<TEntityType, object>(k => null));
var methodCallExpression = (sortMethod.Body as MethodCallExpression);
if (methodCallExpression == null)
throw new Exception("Oops");
var method = methodCallExpression.Method.GetGenericMethodDefinition();
var genericSortMethod = method.MakeGenericMethod(typeof(TEntityType), prop.Type);
var orderedQuery = (IOrderedEnumerable<TEntityType>)genericSortMethod.Invoke(query, new object[] query, sortLambda.Compile() );
return orderedQuery;
或者,如果您想在 IQueryable
上使用它(例如,如果您使用的是 EF)
IOrderedQueryable<TEntityType> SortMeDynamically<TEntityType>(IQueryable<TEntityType> query, string propertyname)
var param = Expression.Parameter(typeof(TEntityType), "s");
var prop = Expression.PropertyOrField(param, propertyname);
var sortLambda = Expression.Lambda(prop, param);
Expression<Func<IOrderedQueryable<TEntityType>>> sortMethod = (() => query.OrderBy<TEntityType, object>(k => null));
var methodCallExpression = (sortMethod.Body as MethodCallExpression);
if (methodCallExpression == null)
throw new Exception("Oops");
var method = methodCallExpression.Method.GetGenericMethodDefinition();
var genericSortMethod = method.MakeGenericMethod(typeof(TEntityType), prop.Type);
var orderedQuery = (IOrderedQueryable<TEntityType>)genericSortMethod.Invoke(query, new object[] query, sortLambda );
return orderedQuery;
【讨论】:
以上是关于LINQ to Entities OrderBy 表达式树的主要内容,如果未能解决你的问题,请参考以下文章
分页错误:仅 LINQ to Entities 中的排序输入支持“跳过”方法。方法 'OrderBy' 必须在方法 'Skip' 之前调用
在 LINQ to Entities 查询中无法构造实体或复杂类型“Cits.Data.LineImg”。
为啥 LINQ-to-Entities 将此查询放在子选择中?