2016-11-15 126 views
2

我希望能够使用lambda表达式获得OrderBy查询,以便使用TOP(n)关键字(大性能提升)获得SQL查询。在linq查询中设置动态排序名称字段

我可以,如果我specifiy做到这一点...

PaginatedList = query.OrderBy(x => x.QuoteID).Skip(() => skipValue).Take(() => pageSize) 

但因为我想要的排序依据字段设置为通过名字的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 does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression."

这个我试过那是类型的不

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) 

而且我得到这个错误:

"Unable to create a constant value of type [...]. Only primitive types or enumeration types are supported in this context"

我敢肯定有办法做到这一点,但目前不知道如何。

+0

感谢所有的建议,我发现每个人的最佳解决方案是在答案为:http://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet – Saleh

+0

必须把信用发现重复问题的人正是我所需要的,非常感谢! !一直在寻找这个老旧的 – Saleh

回答

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); 
+0

这也适用于通过在一个方向上排序,但'source.Expression'需要'Query.Expression'真的简短的解决方案 – Saleh

+0

请注意,在我的代码中,命名约定应该是小写'query'作为它是一个变量 – Saleh

+0

固定变量名称。 Query是变量在OP上的命名方式。 – wdosanjos

1

被复制到propertyInfo的值只是一个Object,因为这是GetProperty()返回的类型。将鼠标悬停在var上,您会确认。

对于对象不存在GetValue方法,因此您需要在调用GetValue之前将其转换为正确的类型。

2

你需要创建一个表达式来选择property.From此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)...;