使用排序表达式列表对可查询进行排序

时间:2016-06-24 22:03:48

标签: c# linq sorting repository-pattern

我正在构建一个存储库,并希望能够将一个排序列表传递给一个函数,以便以正确的顺序接收实体并可能被分页。

我发现linq会正确排序,如果你使用反向排序列表并对每个排序表达式使用Orderby ..

        foreach (var s in sorts.Reverse())
        {
            query = query.OrderBy(s);
        }

然而,在测试添加排序方向时,我发现它只采用第一个排序方向,并且似乎在每种排序上应用该方向。

    private void applySorts(ref IQueryable<TEntity> query, Dictionary<Expression<Func<TEntity, dynamic>>, string> sorts)
    {
        if (sorts != null)
        {
            foreach (var s in sorts.Reverse())
            {
                Expression<Func<TEntity, dynamic>> expr = s.Key;
                string dir = s.Value;
                if (dir == "d")
                {
                    query = query.OrderByDescending(expr);
                }
                else
                {
                    query = query.OrderBy(expr);
                }
            }
        }
    }

我最初尝试在第一次排序时使用OrderBy,然后切换到ThenBy,但这是不可能的,因为ThenBy需要一种IOrderedQueryable。

我想注意字典的使用可能不是最好的,如果你有任何更好的想法请分享。但是,我只是想让它运行起来,看看情况如何。

我正在使用C#,Linq和Entity Framework。

提前感谢您的时间。

更新:不幸的是我发现这不支持排序数字。错误(无法将类型'System.Int32'强制转换为'System.Object'。)

2 个答案:

答案 0 :(得分:1)

在语法上,您只需要IOrderedQueryable类型的临时变量。

我会尝试类似的事情:

    private void applySorts(ref IQueryable<TEntity> query, Dictionary<Expression<Func<TEntity, dynamic>>, string> sorts)
{
    if (sorts != null)
    {
        IOrderedQueryable<TEntity> tempQuery = null;
        bool isFirst = true;
        foreach (var s in sorts.Reverse())
        {
            Expression<Func<TEntity, dynamic>> expr = s.Key;
            string dir = s.Value;
            if (first) 
            {
                first = false;
                if (dir == "d")
                {
                    tempQuery = query.OrderByDescending(expr);
                }
                else
                {
                    tempQuery = query.OrderBy(expr);
                }
            }
            else 
            {   
                if (dir == "d")
                {
                    tempQuery = tempQuery.ThenByDescending(expr);
                }
                else
                {
                    tempQuery = tempQuery.ThenBy(expr);
                }
            }
        }
        query = tempQuery;
    }
}

编辑:

上述解决方案的关键是IOrderedQueryable是一个IQueryable。

我自己没试过。但是,我强调这只是一种语法解决方案。

答案 1 :(得分:0)

您可以使用ThenBy()方法将过滤器链接起来:

bool first = true;

foreach(var s in sorts) 
{
    query = first ? query.OrderBy(s) : query.ThenBy(s);
}
// It will became like query.OrderBy(a => a.A).ThenBy(a => a.B).ThenBy(a => a.C)...

如果您知道要对其进行排序的属性,您还可以使用LINQ查询中的多个列进行排序:

var result = (from row in list
              orderby row.A, row.B, row.C
              select row).ToList();