LINQ to Entities OrderBy 表达式树
LINQ to Entities OrderBy Expression Tree
我正在尝试编写一个 LINQ 查询来 orderBy 一个由字符串值给出的动态 属性。
这是我的原始代码:
Expression<Func<T, dynamic>> orderBy = i => i.GetType().GetProperty("PropertyName").GetValue(null);
当我尝试 运行 这个 orderBy 时,我得到了以下异常:
LINQ to Entities does not recognize the method
'System.Object GetValue(System.Object)' method, and this method cannot
be translated into a store expression.
我试图通过创建一个表达式树来解决这个问题,它会给我相同的结果。根据参数,代码应该能够 return 任何类型,但我在使用 return 类型时遇到了问题。如果我不转换值,我会得到一个不同的错误,指出 w Nullable DateTime can't be converted to 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);
和我的新例外:
Unable to cast the type
'System.Nullable`1[[System.DateTime]]' to type
'System.Object'. LINQ to Entities only supports casting EDM primitive
or enumeration types.
如何编写此表达式树来实现 return 动态类型?还有我应该在 LINQ 中执行此操作的更好方法吗?
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 查询来 orderBy 一个由字符串值给出的动态 属性。
这是我的原始代码:
Expression<Func<T, dynamic>> orderBy = i => i.GetType().GetProperty("PropertyName").GetValue(null);
当我尝试 运行 这个 orderBy 时,我得到了以下异常:
LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression.
我试图通过创建一个表达式树来解决这个问题,它会给我相同的结果。根据参数,代码应该能够 return 任何类型,但我在使用 return 类型时遇到了问题。如果我不转换值,我会得到一个不同的错误,指出 w Nullable DateTime can't be converted to 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);
和我的新例外:
Unable to cast the type 'System.Nullable`1[[System.DateTime]]' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types.
如何编写此表达式树来实现 return 动态类型?还有我应该在 LINQ 中执行此操作的更好方法吗?
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;
}