我有一个查询,我需要根据查询字符串参数进行ordeby。例如,如果sortby参数是price,Query需要随价格变化。如果其评级比更改查询按评级排序。
我知道PredicateBuilder可以执行And和OR的操作但是如何进行动态ordeby linq查询。
答案 0 :(得分:21)
如果你确切知道哪些是可用于订购的可能参数,那么Jon的答案是最好的。但是,如果您有未知数量的参数,则可以动态构建表达式。 e.g:
class Program
{
static void Main(string[] args)
{
var people = new[]{
new Person { Name = "David", Age = 40 },
new Person { Name = "Maria", Age = 12 },
new Person { Name = "Lucas", Age = 45 }
}.AsQueryable();
foreach (var p in people.OrderBy("Age"))
{
Console.Write(p.Name);
}
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
}
static class IQueryableExtensions
{
public static IQueryable<T> OrderBy<T>(this IQueryable<T> items, string propertyName)
{
var typeOfT = typeof(T);
var parameter = Expression.Parameter(typeOfT, "parameter");
var propertyType = typeOfT.GetProperty(propertyName).PropertyType;
var propertyAccess = Expression.PropertyOrField(parameter, propertyName);
var orderExpression = Expression.Lambda(propertyAccess, parameter);
var expression = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { typeOfT, propertyType }, items.Expression, Expression.Quote(orderExpression));
return items.Provider.CreateQuery<T>(expression);
}
}
答案 1 :(得分:15)
好吧,你可以使用switch语句或类似的东西:
IQueryable<Foo> query = ...;
switch (orderByParameter)
{
case "price":
query = query.OrderBy(x => x.Price);
break;
case "rating":
query = query.OrderBy(x => x.Rating);
break;
// etc
}
您也可以使用反射来完成,但假设您的字段数量有限,这很可能是最简单的方法。
答案 2 :(得分:2)
扩展@lontivero的答案。
如果要对升序和降序的多个项目进行动态排序,可以执行与此类似的操作。添加OrderByDescending,ThenBy,ThenByDescending方法
static class IQueryableExtensions
{
public static IQueryable<T> OrderBy<T>(this IQueryable<T> items, string propertyName)
{
var typeOfT = typeof(T);
var parameter = Expression.Parameter(typeOfT, "parameter");
var propertyType = typeOfT.GetProperty(propertyName).PropertyType;
var propertyAccess = Expression.PropertyOrField(parameter, propertyName);
var orderExpression = Expression.Lambda(propertyAccess, parameter);
var expression = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { typeOfT, propertyType }, items.Expression, Expression.Quote(orderExpression));
return items.Provider.CreateQuery<T>(expression);
}
public static IQueryable<T> OrderByDescending<T>(this IQueryable<T> items, string propertyName)
{
var typeOfT = typeof(T);
var parameter = Expression.Parameter(typeOfT, "parameter");
var propertyType = typeOfT.GetProperty(propertyName).PropertyType;
var propertyAccess = Expression.PropertyOrField(parameter, propertyName);
var orderExpression = Expression.Lambda(propertyAccess, parameter);
var expression = Expression.Call(typeof(Queryable), "OrderByDescending", new Type[] { typeOfT, propertyType }, items.Expression, Expression.Quote(orderExpression));
return items.Provider.CreateQuery<T>(expression);
}
public static IQueryable<T> ThenBy<T>(this IQueryable<T> items, string propertyName)
{
var typeOfT = typeof(T);
var parameter = Expression.Parameter(typeOfT, "parameter");
var propertyType = typeOfT.GetProperty(propertyName).PropertyType;
var propertyAccess = Expression.PropertyOrField(parameter, propertyName);
var orderExpression = Expression.Lambda(propertyAccess, parameter);
var expression = Expression.Call(typeof(Queryable), "ThenBy", new Type[] { typeOfT, propertyType }, items.Expression, Expression.Quote(orderExpression));
return items.Provider.CreateQuery<T>(expression);
}
public static IQueryable<T> ThenByDescending<T>(this IQueryable<T> items, string propertyName)
{
var typeOfT = typeof(T);
var parameter = Expression.Parameter(typeOfT, "parameter");
var propertyType = typeOfT.GetProperty(propertyName).PropertyType;
var propertyAccess = Expression.PropertyOrField(parameter, propertyName);
var orderExpression = Expression.Lambda(propertyAccess, parameter);
var expression = Expression.Call(typeof(Queryable), "ThenByDescending", new Type[] { typeOfT, propertyType }, items.Expression, Expression.Quote(orderExpression));
return items.Provider.CreateQuery<T>(expression);
}
}