有没有办法通过具有不同排序量的 IQueryable 进行排序

Rob*_*ite 3 c# linq entity-framework sql-order-by

例如,我想尝试这样的事情。排序部分可能没有、1 个或多个按不同顺序排序的列。但我无法使用该ThenBy方法,因为它仅在OrderBy. 下面的代码将不断将顺序重置为排序列表中的最后一项。我也不想更改方法签名。非常感谢您的帮助,谢谢。

public IQueryable<Person> FilterList(string forename, List<Sorting> sorting)
{
    IQueryable<Person> query = dc.Set<Person>();

    if(!string.IsNullOrEmpty(forename)){
        query = query.Where(w=>w.Forename.Contains(forename));

    foreach(var sort in sorting)
    {
        switch(sort.By)
        {
            case "asc":
               switch(sort.Sort)
               {
                   case "forename":
                       query = query.OrderBy(o=>o.Forename);
                       break;

                   case "surname":
                       query = query.OrderBy(o=>o.Surname);
                       break;
               }
               break;

            case "desc":
               switch(sort.Sort)
               {
                   case "forename":
                       query = query.OrderByDescending(o=>o.Forename);
                       break;

                   case "surname":
                       query = query.OrderByDescending(o=>o.Surname);
                       break;
               }
               break;
        }
    }

    return query;
}

public class Sorting
{
    public string Sort{get;set;}
    public string By{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

AgentFire 的回答实际上是适当的,但对于每种情况的特殊情况来说有点啰嗦。我会添加一个扩展方法:

编辑:显然,下面的代码无法正确确定查询是否已排序;显然,即使是无序版本也实现了IOrderedQueryable<T>。用于source.Expression.Type检查IOrderedQueryable<T>显然有效,但我将这段代码留在这里作为更合乎逻辑的方法 - 而且这个“修复”听起来比我想要的带有我名字的答案更脆弱:)

public static IOrderedQueryable<T> AddOrdering<T, TKey>(
    this IQueryable<T> source,
    Expression<Func<T, TKey>> keySelector,
    bool descending)
{
    IOrderedQueryable<T> ordered = source as IOrderedQueryable<T>;
    // If it's not ordered yet, use OrderBy/OrderByDescending.
    if (ordered == null)
    {
        return descending ? source.OrderByDescending(keySelector)
                          : source.OrderBy(keySelector);
    }
    // Already ordered, so use ThenBy/ThenByDescending
    return descending ? ordered.ThenByDescending(keySelector)
                      : ordered.ThenBy(keySelector);
}
Run Code Online (Sandbox Code Playgroud)

那么你的调用代码就变成:

foreach(var sort in sorting)
{
    bool descending = sort.By == "desc";
    switch (sort.Sort)
    {
        case "forename":
            query = query.AddOrdering(o => o.Forename, descending);
            break;
        case "surname":
            query = query.AddOrdering(o => o.Surname, descending);
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,每个附加的排序选项只会增加很小的代码开销。