排序/排序未确定的列数(LINQ \ Entity Framework)

时间:2017-01-25 23:43:42

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

需要根据未确定的列数(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();

2 个答案:

答案 0 :(得分:2)

问题是ThenBy没有在IQueryable上定义,而是在IOrderedQueryable接口上定义(这是IQueryable.OrderBy返回的内容)。因此,您需要为IOrderedQueryable定义一个新变量,以便进行后续的ThenBy调用。我稍微更改了原始代码以使用System.Data.DataTable(以获得与“param”对象类似的结构)。该代码还假定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));
}

答案 1 :(得分:0)

你应该在OrderBy之后写一下ThenBy:

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