【问题标题】:Sort/Order an Undetermined Number of Columns (LINQ\Entity Framework)对未确定的列数进行排序/排序(LINQ\Entity Framework)
【发布时间】:2017-01-25 23:43:42
【问题描述】:

需要根据不确定的列数(1 或更多)对数据列表进行排序/排序。

我正在尝试做的是遍历所需的列并根据它们的编号将 OrderBy 或 ThenBy 添加到查询列表中,但我不成功...

这样做了,但它没有编译:

var query = GetAllItems(); //returns a IQueriable list of items

//for each selected column
for (int i = 0; i < param.Columns.Length; i++)
{
    if (i == 0)
    {
        query = query.OrderBy(x => x.GetType().GetProperty(param.Columns[i].Name));
    }
    else
    {
        //ERROR: IQueriable does not contain a definition for "ThenBy" and no extension method "ThenBy"...
        query = query.ThenBy(x => x.GetType().GetProperty(param.Columns[i].Data));
    }
}

我该如何解决这个问题?或者有什么替代方法可以满足这个要求?

解决方案: @Dave-Kidder 的解决方案经过深思熟虑,解决了我遇到的编译错误。只有一个问题,OrderBy 仅在 ToList() 强制转换后执行(实际上是对结果进行排序)。这是一个问题,因为我无法将 ToList 转换回 IOrderedQueryable。 所以,经过一番研究,我找到了一个解决我所有问题的解决方案。

.Net 4.0 动态语言功能的 Microsoft 程序集:https://github.com/kahanu/System.Linq.Dynamic

using System.Linq.Dynamic; //need to install this package

更新代码:

var query = GetAllItems(); //returns a IQueriable list of items

List<string> orderByColumnList = new List<string>(); //list of columns to sort

for (int i = 0; i < param.Columns.Length; i++)
{
    string column = param.Columns[i].Name;
    string direction = param.Columns[i].Dir;

    //ex.: "columnA ASC"
    string orderByColumn = column + " " + direction;

    //add column to list
    orderByColumnList.Add(orderBy);
}

//convert list to comma delimited string
string orderBy = String.Join(",", orderByColumnList.ToArray());

//sort by all columns, yay! :-D
query.OrderBy(orderBy).ToList();

【问题讨论】:

    标签: entity-framework linq entity-framework-6 sql-order-by


    【解决方案1】:

    问题是 ThenBy 不是在 IQueryable 上定义的,而是在 IOrderedQueryable 接口上定义的(这是IQueryable.OrderBy 返回的)。因此,您需要为 IOrderedQueryable 定义一个新变量,以便执行后续的 ThenBy 调用。我稍微更改了原始代码以使用 System.Data.DataTable (以获得与您的“参数”对象类似的结构)。该代码还假设 DataTable 中至少有一列。

    // using System.Data.DataTable to provide similar object structure as OP
    DataTable param = new DataTable();
    IQueryable<DataTable> query = new List<DataTable>().AsQueryable();
    
    // OrderBy returns IOrderedQueryable<TSource>, which is the interface that defines
    // "ThenBy" so we need to assign it to a different variable if we wish to make subsequent
    // calls to ThenBy
    var orderedQuery = query.OrderBy(x => x.GetType().GetProperty(param.Columns[0].ColumnName));
    
    //for each other selected column
    for (int i = 1; i < param.Columns.Count; i++)
    {
        orderedQuery = orderedQuery.ThenBy(x => x.GetType().GetProperty(param.Columns[i].ColumnName));
    }
    

    【讨论】:

    • 感谢@Dave,它完成了这项工作。只有一个小细节使事情无法正常工作。为了使订单发生并实际执行,查询必须使用 .ToList()。但是当使用 ToList() 时,一切又崩溃了……
    【解决方案2】:

    你应该像这样在 OrderBy 之后写 ThenBy:

    query = query
               .OrderBy(t=> // your condition)
               .ThenBy(t=> // next condition);
    

    【讨论】:

    • 我知道,我的主要问题是动态地为未定义的列数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多