我希望能够使用lambda表达式获得OrderBy
查询,以便获得带有TOP(n)关键字的SQL查询(提高性能)。
如果我指定......我能做到这一点。
PaginatedList = query.OrderBy(x => x.QuoteID).Skip(() => skipValue).Take(() => pageSize)
但是因为我希望orderBy字段通过UI选择名称来动态,我想做这样的事情:
var propertyInfo = typeof(Data.Quote).GetProperty(sortName);
Expression<Func<Data.Quote, object>> orderField = x => propertyInfo.GetValue(x, null);
PaginatedList = query.OrderBy(orderField).Skip(() => skipValue).Take(() => pageSize)
这给了我错误:
“LINQ to Entities无法识别方法'System.Object GetValue(System.Object)'方法,此方法无法翻译 进入商店表达。“
我尝试过这种类型Expression<Func<T, object>>
var propertyInfo = typeof(Data.Quote).GetProperty(sortName);
Func<Data.Quote, object> orderField = x => propertyInfo.GetValue(x, null);
PaginatedList = query.OrderBy(x => orderField).Skip(() => skipValue).Take(() => pageSize)
我收到了这个错误:
“无法创建[...]类型的常量值。只有基本类型 或者在此上下文中支持枚举类型“
我确信有办法实现这一目标,但目前还不确定如何。
答案 0 :(得分:3)
以下是如何实现您的目标:
var propertyInfo = typeof(Data.Quote).GetProperty(sortName);
ParameterExpression parameter = Expression.Parameter(typeof(T), "s");
MemberExpression property = Expression.Property(parameter, propertyInfo);
LambdaExpression sort = Expression.Lambda(property, parameter);
MethodCallExpression call = Expression.Call(
typeof(Queryable),
"OrderBy",
new[] {typeof(T), property.Type},
Query.Expression,
Expression.Quote(sort));
var orderedQuery = (IOrderedQueryable<T>)Query.Provider.CreateQuery<T>(call);
PaginatedList = orderedQuery.Skip(skipValue).Take(pageSize);
答案 1 :(得分:2)
而不是你需要创建一个表达式来选择那个属性。从这个source:
public static class Utility
{
//makes expression for specific prop
public static Expression<Func<TSource, object>> GetExpression<TSource>(string propertyName)
{
var param = Expression.Parameter(typeof(TSource), "x");
Expression conversion = Expression.Convert(Expression.Property
(param, propertyName), typeof(object)); //important to use the Expression.Convert
return Expression.Lambda<Func<TSource, object>>(conversion, param);
}
public static IOrderedQueryable<TSource>
OrderBy<TSource>(this IQueryable<TSource> source, string propertyName)
{
return source.OrderBy(GetExpression<TSource>(propertyName));
}
}
然后您可以按照我在下面显示的顺序订购:
var result=Query.OrderBy(sortName)...;
答案 2 :(得分:1)
复制到propertyInfo
的值只是一个Object,因为它是GetProperty()
返回的类型。将鼠标悬停在var
上即可确认。
对象不存在GetValue
方法,因此您需要在调用GetValue
之前将其强制转换为正确的类型。