使用属性名称作为字符串排序 [英] Sorting using property name as string
问题描述
我希望我的Web API能够按这样的字符串参数对输出进行排序:
http://myapi.com/api/people?skip=0&take=50&orderBy=lastName&descending=true
.
因为我的API中还具有分页支持(使用 skip
和 take
),所以我希望 orderBy
和下降
参数直接应用于SQL查询,以便正确的结果来自数据库.
但是,在执行此操作时,仅尝试使用字符串比较将 orderBy
的参数与我希望排序的类的实际属性进行匹配时,代码将变得非常难以管理.
我找到了解决方案
链接中的解决方案使用的是"Expression.Convert",在大多数情况下,它们不适用于LINQ to Entities.
这是一种有效的扩展方法:
公共静态IOrderedQueryable< TSource>OrderBy< TSource>(此IQueryable< TSource>源,字符串propertyName){//LAMBDA:x =>x.[PropertyName]var parameter = Expression.Parameter(typeof(TSource),"x");表达式属性= Expression.Property(参数,propertyName);var lambda = Expression.Lambda(property,parameter);//反射:source.OrderBy(x => x.Property)var orderByMethod = typeof(Queryable).GetMethods().First(x => x.Name =="OrderBy"&& x.GetParameters().Length == 2);var orderByGeneric = orderByMethod.MakeGenericMethod(typeof(TSource),property.Type);var result = orderByGeneric.Invoke(null,new object [] {source,lambda});返回(IOrderedQueryable< TSource>)结果;}
免责声明:我是项目 EF + 的所有者
您可以在我的存储库中找到其他按属性名称排序的方法: GitHub >
- OrderByDescending
- 然后
- ThenByDescending
- AddOrAppendOrderBy
- AddOrAppendOrderByDescending
编辑:回答子问题
是否可能使用类似以下内容按导航属性进行排序这个,例如属性名称"NavigationProperty.PropertyName"
是的,您可以拆分字符串并循环以使用属性路径创建表达式,也可以使用真实的表达式求值器.
免责声明:我是该项目的所有者 Eval-Expressions.NET
该库允许您动态执行所有LINQ方法.
请参阅: LINQ Dynamic
var结果= list.OrderByDynamic(x =>"NavigationProperty.PropertyName");
I would like my Web API to be able to sort its output by a string parameter such as this one:
http://myapi.com/api/people?skip=0&take=50&orderBy=lastName&descending=true
.
Because I also have pagination support (with skip
and take
) in my API, I would like the orderBy
and descending
parameter to be applied to the SQL query directly, so that the correct result comes from the database.
When doing this however, the code can become very hard to manage when trying to match the parameters for orderBy
with the actual properties of the classes I wish to sort by just using string comparisons.
I have found a solution which is supposed to work with LINQ to Entities and thus also with the new EF7, however when I try to compile this code using the new Core CLR, I get the following message:
Error CS1503 Argument 2: cannot convert from 'System.Linq.Expressions.Expression>' to 'string'
The code from the solution that fails is the OrderBy<T>
method:
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
{
return source.OrderBy(ToLambda<T>(propertyName));
}
It seems like the new Core CLR does not support this attempt. Is there another way to get the solution to work with the new CLR? If no, what other alternatives do I have to enable sorting using EF7 without resulting in countless if
or switch
statements to compare the input strings to the property names?
The solution from your link uses an "Expression.Convert" which most of the time doesn't work with LINQ to Entities.
Here is a working extension method:
public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName)
{
// LAMBDA: x => x.[PropertyName]
var parameter = Expression.Parameter(typeof(TSource), "x");
Expression property = Expression.Property(parameter, propertyName);
var lambda = Expression.Lambda(property, parameter);
// REFLECTION: source.OrderBy(x => x.Property)
var orderByMethod = typeof(Queryable).GetMethods().First(x => x.Name == "OrderBy" && x.GetParameters().Length == 2);
var orderByGeneric = orderByMethod.MakeGenericMethod(typeof(TSource), property.Type);
var result = orderByGeneric.Invoke(null, new object[] { source, lambda });
return (IOrderedQueryable<TSource>)result;
}
Disclaimer: I'm the owner of the project EF+ on GitHub.
You can find other methods to order by property name in my repository: GitHub
- OrderByDescending
- ThenBy
- ThenByDescending
- AddOrAppendOrderBy
- AddOrAppendOrderByDescending
EDIT: Answer sub-question
Is it possibly to sort by navigation properties using something like this, e.g. a property name "NavigationProperty.PropertyName"
Yes, you can either split the string and loop to create the expression with the property path or use a real expression evaluator.
Disclaimer: I'm the owner of the project Eval-Expressions.NET
This library allows you to execute all LINQ method dynamically.
See: LINQ Dynamic
var result = list.OrderByDynamic(x => "NavigationProperty.PropertyName");
这篇关于使用属性名称作为字符串排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!