使用屬性名稱作為字符串排序

asp.net asp.net-core c# entity-framework-core linq

我希望我的Web API能夠通過字符串參數對其輸出進行排序,例如:

http://myapi.com/api/people?skip=0&take=50&orderBy=lastName&descending=true

因為我的API中也有分頁支持(使用skiptake ),所以我希望orderBydescending參數直接應用於SQL查詢,以便正確的結果來自數據庫。

但是,在執行此操作時,在嘗試將orderBy的參數與我希望通過僅使用字符串比較進行排序的類的實際屬性進行匹配時,代碼可能變得非常難以管理。

我找到了一個解決方案 ,它應該與LINQ to Entities一起使用,因此也適用於新的EF7,但是當我嘗試使用新的Core CLR編譯此代碼時,我收到以下消息:

錯誤CS1503參數2:無法從'System.Linq.Expressions.Expression>'轉換為'string'

失敗的解決方案的代碼是OrderBy<T>方法:

public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
{
    return source.OrderBy(ToLambda<T>(propertyName));
}

似乎新的Core CLR不支持這種嘗試。有沒有其他方法可以使解決方案與新的CLR一起使用?如果不是,我還有什麼其他選擇來使用EF7進行排序而不會導致無數ifswitch語句將輸入字符串與屬性名稱進行比較?

一般承認的答案

來自鏈接的解決方案使用“Expression.Convert”,大多數情況下,它不適用於LINQ to Entities。

這是一個有效的擴展方法:

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;
}

免責聲明 :我是GitHub上EF +項目的所有者。

您可以在我的存儲庫中找到按屬性名稱排序的其他方法: GitHub

  • OrderByDescending
  • ThenBy
  • ThenByDescending
  • AddOrAppendOrderBy
  • AddOrAppendOrderByDescending

編輯 :回答子問題

是否可以使用類似的東西對導航屬性進行排序,例如屬性名稱“NavigationProperty.PropertyName”

是的,您可以拆分字符串和循環以使用屬性路徑創建表達式或使用實際表達式求值程序。

免責聲明 :我是Eval-Expressions.NET項目的所有者

該庫允許您動態執行所有LINQ方法。

請參閱: LINQ Dynamic

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;
}



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因