14

我有一个报告界面,最终用户可以在其中为返回的报告的排序顺序选择多个字段。我遇到的问题是我无法真正链接 OrderBy / ThenBy 方法,因为我正在遍历排序字段列表。我在想这样的事情:

foreach (string sort in data.SortParams)
{
    switch (sort)
    {
        case "state":
            query = query.ThenBy(l => l.RegionCode);
            break;
        case "type":
            query = query.ThenBy(l => l.Type);
            break;
        case "color":
            query = query.ThenBy(l => l.Color);
            break;
        case "category":
            query = query.OrderBy(l => l.Category);
            break;
    }
}

(注意:为简单起见,我删除了确定这是否是第一个排序项的开关。)

关于如何遍历集合以确定排序顺序的任何想法?

4

3 回答 3

23

如果您使用初始“​​种子”OrderBy,您可以做您想做的事:

编辑您需要在附加子句之前先调用OrderBy创建一个IOrderedEnumerable(或):IOrderedQueryableThenBy

var orderedQuery = query.OrderBy(l => 0);
foreach (string sort in data.SortParams)
{
    switch (sort)
    {
        case "state":
            orderedQuery = orderedQuery.ThenBy(l => l.RegionCode);
            break;
        case "type":
            orderedQuery = orderedQuery.ThenBy(l => l.Type);
            break;
        case "color":
            orderedQuery = orderedQuery.ThenBy(l => l.Color);
            break;
        case "category":
            orderedQuery = orderedQuery.ThenBy(l => l.Category);
            break;
    }
}
query = orderedQuery;  // cast back to original type.

如果您想要更灵活的东西,请查看此答案

于 2012-11-21T16:20:51.400 回答
14

我创建了这些扩展方法来解决问题中所述的相同问题:

public static class QueryableExtensions
{
    public static IOrderedQueryable<T> AppendOrderBy<T, TKey>(this IQueryable<T> query, Expression<Func<T, TKey>> keySelector)
        => query.Expression.Type == typeof(IOrderedQueryable<T>)
        ? ((IOrderedQueryable<T>) query).ThenBy(keySelector)
        : query.OrderBy(keySelector);

    public static IOrderedQueryable<T> AppendOrderByDescending<T, TKey>(this IQueryable<T> query, Expression<Func<T, TKey>> keySelector)
        => query.Expression.Type == typeof(IOrderedQueryable<T>)
            ? ((IOrderedQueryable<T>)query).ThenByDescending(keySelector)
            : query.OrderByDescending(keySelector);
}

然后可以将问题中的代码重构为:

foreach (string sort in data.SortParams)
{
    switch (sort)
    {
        case "state":
            query = query.AppendOrderBy(l => l.RegionCode);
            break;
        case "type":
            query = query.AppendOrderBy(l => l.Type);
            break;
        case "color":
            query = query.AppendOrderBy(l => l.Color);
            break;
        case "category":
            query = query.AppendOrderBy(l => l.Category);
            break;
    }
}

备注这些扩展方法只检查表达式树中的前一个表达式以确定是否使用OrderByor ThenBy,中间不允许其他表达式。如果您还想解决这个问题,则必须遍历完整的树,这可能只会增加您不想要的开销:)

于 2017-08-03T13:42:10.940 回答
-1

从可读性的角度来看,可能在一个 Linq 查询中使用所有功能并不是最佳选择。我会使用 IQueryable 在内存中构造您的查询。使用类似的 switch 语句(但使用 IQueryable),然后最后执行 .ToList(即枚举)以在服务器上执行所需的查询。

于 2012-11-21T16:10:48.220 回答