我正在构建一个存储库,并希望能够将一个排序列表传递给一个函数,以便以正确的顺序接收实体并可能被分页。
我发现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'。)
答案 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();