簡體   English   中英

如何動態執行多個 Linq to Entities 排序

[英]How to perform multiple Linq to Entities orderings dynamically

所以我的問題是這樣的; 在 C# 代碼中,我需要在 Linq to Entities 的幫助下根據輸入參數對實體集執行多次排序。 有三列要排序,排序列的順序本身是可變的(這意味着對於每個排序,我需要查找要排序的列)。 我怎樣才能做到這一點?

我有一些應該可以工作的代碼,但是我重復了太多,因為我無法參數化我的操作(Linq to Entities 是非常嚴格的wrt。我可以在我的 lambdas 中做什么)。 請建議我如何根據DRY原則重寫我的代碼,也許在 T4 代碼生成的幫助下?

下面的代碼應該說明我的問題。 這是真實代碼的摘錄,為簡潔起見,如果我應該包含更多內容,請告訴我。 orderSpecs變量是一個“訂單規范”數組,每個規范指定要排序的列以及是否以降序方式排序。 orderSpecs數組至少有一個元素,因此至少執行了一種排序。

using (var db = new MyContainer())
{
    var orderSpec = orderSpecs[0];
    IQueryable<DbVersion> dVersions = null;
    if (orderSpec.Column == 0)
    {
        if (orderSpec.Descending)
        {
            dVersions = db.Versions.OrderByDescending(ver => ver.Name);
        }
        else
        {
            dVersions = db.Versions.OrderBy(ver => ver.Name);
        }
    }
    else if (orderSpec.Column == 1)
    {
        if (orderSpec.Descending)
        {
            dVersions = db.Versions.OrderByDescending(ver => ver.Built);
        }
        else
        {
            dVersions = db.Versions.OrderBy(ver => ver.Built);
        }
    }
    else if (orderSpec.Column == 2)
    {
        if (orderSpec.Descending)
        {
            dVersions = db.Versions.OrderByDescending(ver => ver.Id);
        }
        else
        {
            dVersions = db.Versions.OrderBy(ver => ver.Id);
        }
    }

    foreach (var spec in orderSpecs.Skip(1))
    {
        if (spec.Column == 0)
        {
            if (spec.Descending)
            {
                dVersions = dVersions.ThenByDescending(ver => ver.Name);
            }
            else
            {
                dVersions = dVersions.ThenBy(ver => ver.Name);
            }
        }
        else if (spec.Column == 1)
        {
            if (spec.Descending)
            {
                dVersions = dVersions.ThenByDescending(ver => ver.Built);
            }
            else
            {
                dVersions = dVersions.ThenBy(ver => ver.Built);
            }
        }
        else if (spec.Column == 2)
        {
            if (spec.Descending)
            {
                dVersions = dVersions.ThenByDescending(ver => ver.Id);
            }
            else
            {
                dVersions = dVersions.ThenBy(ver => ver.Id);
            }
        }
    }

如何創建一個字典來將這些導致這些巨大的 if-else 構造的列映射到屬性。 看起來像這樣:

using (var db = new MyContainer())
{
    var orderSpec = orderSpecs[0];
    IOrderedEnumerable<DbVersion> dVersions;

    var mapping = new Dictionary<int, Func<DbVersion, object>>()
    {
        { 0, ver => ver.Name },
        { 1, ver => ver.Built },
        { 2, ver => ver.Id }
    };

    if (orderSpec.Descending)
        dVersions = db.Versions.OrderByDescending(mapping[orderSpec.Column]);
    else
        dVersions = db.Versions.OrderBy(mapping[orderSpec.Column]);

    foreach (var spec in orderSpecs.Skip(1))
    {
        if (spec.Descending)
            dVersions = dVersions.ThenByDescending(mapping[spec.Column]);
        else
            dVersions = dVersions.ThenBy(mapping[spec.Column]);
    }
}

對於Untype :您還可以使用動態 Linq 庫: 使用 LINQ 動態查詢庫

在此處輸入圖片說明

要么

全文: 處理 GridView.OnSorting() 並使用 LINQ 動態創建排序表達式

對於Typed :您可以進行如下動態排序,刪除您編寫的代碼

如何對列名和排序方向未修復的名為 person 的類進行排序

IEnumerable<Person> persons = GetPersons();
    persons = persons.OrderBy(e.SortExpression, e.SortDirection);

人物類

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

使用表達式樹對數據進行排序的通用方法

public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> collection, 
       string columnName, SortDirection direction)
{
    ParameterExpression param = Expression.Parameter(typeof(T), "x"); // x
    Expression property = Expression.Property(param, columnName);     // x.ColumnName
    Func<T, object> func = Expression.Lambda<Func<T, object>>(        // x => x.ColumnName
        Expression.Convert(Expression.Property(param, columnName), 
        typeof(object)), param).Compile();

    Func<IEnumerable<T>, Func<T, object>, IEnumerable<T>> expression =
        SortExpressionBuilder<T>.CreateExpression(direction);
    IEnumerable<T> sorted = expression(collection, func);
    return sorted;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM