C# 有没有一种方法可以通过不同订购量的IQueryable进行订购

C# 有没有一种方法可以通过不同订购量的IQueryable进行订购,c#,linq,entity-framework,sql-order-by,C#,Linq,Entity Framework,Sql Order By,例如,我想试试这样的东西。排序PAR可能没有,1个或多个排序列按不同顺序排列。但是我不能使用ThenBy方法,因为它只在OrderBy之后才可用。下面的代码将继续将订单重置为排序列表中的最后一项。我也不想更改方法签名。非常感谢您的帮助,谢谢 public IQueryable<Person> FilterList(string forename, List<Sorting> sorting) { IQueryable<Person> query = d

例如,我想试试这样的东西。排序PAR可能没有,1个或多个排序列按不同顺序排列。但是我不能使用
ThenBy
方法,因为它只在
OrderBy
之后才可用。下面的代码将继续将订单重置为排序列表中的最后一项。我也不想更改方法签名。非常感谢您的帮助,谢谢

public IQueryable<Person> FilterList(string forename, List<Sorting> sorting)
{
    IQueryable<Person> query = dc.Set<Person>();

    if(!string.IsNullOrEmpty(forename)){
        query = query.Where(w=>w.Forename.Contains(forename));

    foreach(var sort in sorting)
    {
        switch(sort.By)
        {
            case "asc":
               switch(sort.Sort)
               {
                   case "forename":
                       query = query.OrderBy(o=>o.Forename);
                       break;

                   case "surname":
                       query = query.OrderBy(o=>o.Surname);
                       break;
               }
               break;

            case "desc":
               switch(sort.Sort)
               {
                   case "forename":
                       query = query.OrderByDescending(o=>o.Forename);
                       break;

                   case "surname":
                       query = query.OrderByDescending(o=>o.Surname);
                       break;
               }
               break;
        }
    }

    return query;
}

public class Sorting
{
    public string Sort{get;set;}
    public string By{get;set;}
}
publicIQueryable过滤器列表(字符串名,列表排序)
{
IQueryable query=dc.Set();
如果(!string.IsNullOrEmpty(forename)){
query=query.Where(w=>w.Forename.Contains(Forename));
foreach(排序中的变量排序)
{
开关(按排序)
{
案例“asc”:
开关(sort.sort)
{
案例“forename”:
query=query.OrderBy(o=>o.Forename);
打破
“姓氏”一案:
query=query.OrderBy(o=>o.lasname);
打破
}
打破
案例“desc”:
开关(sort.sort)
{
案例“forename”:
query=query.OrderByDescending(o=>o.Forename);
打破
“姓氏”一案:
query=query.OrderByDescending(o=>o.姓氏);
打破
}
打破
}
}
返回查询;
}
公共类排序
{
公共字符串排序{get;set;}
由{get;set;}生成的公共字符串
}

您可能需要使用cast:

var sortedQueryable = query as IOrderedQueryable<Person>;

if (sortedQueryable != null)
{
    query = sortedQueryable.ThenBy(o => o.Forename);
}
else
{
    query = query.OrderBy(o => o.Forename);
}

因此,在您的
foreach
循环中,您只需要
if
for
SortMode
并将元组的
Item2
传递给订购方。

您可能需要使用cast:

var sortedQueryable = query as IOrderedQueryable<Person>;

if (sortedQueryable != null)
{
    query = sortedQueryable.ThenBy(o => o.Forename);
}
else
{
    query = query.OrderBy(o => o.Forename);
}

因此,在您的
foreach
循环中,您只需要
如果
for
SortMode
并将元组的
Item2
传递给排序者。

首先按常量排序,这样您就有了一个
IOrderedQueryable
,然后您就可以通过
然后按
方法进行所有自定义排序

public IQueryable<Person> FilterList(string forename, List<Sorting> sorting) {
    IQueryable<Person> query = dc.Set<Person>();
    if(!string.IsNullOrEmpty(forename)){
        query = query.Where(w=>w.Forename.Contains(forename));

    var orderedQuery = query.OrderBy(x => 1);

    foreach(var sort in sorting) {
        switch(sort.By) {
            case "asc":
               switch(sort.Sort) {
                   case "forename":
                       orderedQuery = orderedQuery.ThenBy(o=>o.Forename);
                   break;
                   case "surname":
                       orderedQuery = orderedQuery.ThenBy(o=>o.Surname);
                   break;
               }
            break;
            case "desc":
               switch(sort.Sort) {
                   case "forename":
                       orderedQuery = orderedQuery.ThenByDescending(o=>o.Forename);
                   break;
                   case "surname":
                       orderedQuery = orderedQuery.ThenByDescending(o=>o.Surname);
                   break;
               }
            break;
        }
    }

    return orderedQuery;
}
publicIQueryable过滤器列表(字符串名,列表排序){
IQueryable query=dc.Set();
如果(!string.IsNullOrEmpty(forename)){
query=query.Where(w=>w.Forename.Contains(Forename));
var orderedQuery=query.OrderBy(x=>1);
foreach(排序中的变量排序){
开关(按排序){
案例“asc”:
开关(sort.sort){
案例“forename”:
orderedQuery=orderedQuery.ThenBy(o=>o.Forename);
打破
“姓氏”一案:
orderedQuery=orderedQuery.ThenBy(o=>o.姓氏);
打破
}
打破
案例“desc”:
开关(sort.sort){
案例“forename”:
orderedQuery=orderedQuery.ThenByDescending(o=>o.Forename);
打破
“姓氏”一案:
orderedQuery=orderedQuery.ThenByDescending(o=>o.姓氏);
打破
}
打破
}
}
返回订单查询;
}

首先按常量排序,这样您就有了一个
IOrderedQueryable
,然后您可以通过
然后按
方法进行所有自定义排序

public IQueryable<Person> FilterList(string forename, List<Sorting> sorting) {
    IQueryable<Person> query = dc.Set<Person>();
    if(!string.IsNullOrEmpty(forename)){
        query = query.Where(w=>w.Forename.Contains(forename));

    var orderedQuery = query.OrderBy(x => 1);

    foreach(var sort in sorting) {
        switch(sort.By) {
            case "asc":
               switch(sort.Sort) {
                   case "forename":
                       orderedQuery = orderedQuery.ThenBy(o=>o.Forename);
                   break;
                   case "surname":
                       orderedQuery = orderedQuery.ThenBy(o=>o.Surname);
                   break;
               }
            break;
            case "desc":
               switch(sort.Sort) {
                   case "forename":
                       orderedQuery = orderedQuery.ThenByDescending(o=>o.Forename);
                   break;
                   case "surname":
                       orderedQuery = orderedQuery.ThenByDescending(o=>o.Surname);
                   break;
               }
            break;
        }
    }

    return orderedQuery;
}
publicIQueryable过滤器列表(字符串名,列表排序){
IQueryable query=dc.Set();
如果(!string.IsNullOrEmpty(forename)){
query=query.Where(w=>w.Forename.Contains(Forename));
var orderedQuery=query.OrderBy(x=>1);
foreach(排序中的变量排序){
开关(按排序){
案例“asc”:
开关(sort.sort){
案例“forename”:
orderedQuery=orderedQuery.ThenBy(o=>o.Forename);
打破
“姓氏”一案:
orderedQuery=orderedQuery.ThenBy(o=>o.姓氏);
打破
}
打破
案例“desc”:
开关(sort.sort){
案例“forename”:
orderedQuery=orderedQuery.ThenByDescending(o=>o.Forename);
打破
“姓氏”一案:
orderedQuery=orderedQuery.ThenByDescending(o=>o.姓氏);
打破
}
打破
}
}
返回订单查询;
}

AgentFire的答案实际上是恰当的,但在每种情况下,对于特殊情况都有点冗长。我要添加一个扩展方法:

编辑:显然,下面的代码无法正确确定查询是否已排序;即使是无序版本也显然实现了
IOrderedQueryable
。使用
source.Expression.Type
检查
IOrderedQueryable
显然有效,但我将此代码保留在这里作为更符合逻辑的方法-and因为这个“修复”听起来比我想要一个写着我名字的答案更脆弱:)


这样一来,每个额外的排序选项只会增加一小部分代码开销。

AgentFire的答案实际上是合适的,但对于每种情况的特殊情况,都有点冗长。我要添加一个扩展方法:

编辑:显然,下面的代码无法正确确定查询是否已排序;即使是无序版本也显然实现了
IOrderedQueryable
。使用
source.Expression.Type
检查
IOrderedQueryable
显然有效,但我将此代码保留在这里作为更符合逻辑的方法-and因为这个“修复”听起来比我想要一个写着我名字的答案更脆弱:)


这样一来,每个额外的排序选项只会增加很小的代码开销。

有很多选项可供选择。例如:

bool isSorted = false;

foreach(var sort in sorting)
{
    switch(sort.By)
    {
        case "asc":

           switch(sort.Sort)
           {
               case "forename":
                   if (!isSorted)
                   {
                       query = query .OrderBy(o => o.Forename);
                       isSorted = true;
                   }
                   else
                   {
                       query = ((IOrderedQueryable<Person>)query).ThenBy(o => o.Forename);
                   }
               ...
           }
        break;
        case "desc":
               ...
    }
}
bool isSorted=false;
前面
bool isSorted = false;

foreach(var sort in sorting)
{
    switch(sort.By)
    {
        case "asc":

           switch(sort.Sort)
           {
               case "forename":
                   if (!isSorted)
                   {
                       query = query .OrderBy(o => o.Forename);
                       isSorted = true;
                   }
                   else
                   {
                       query = ((IOrderedQueryable<Person>)query).ThenBy(o => o.Forename);
                   }
               ...
           }
        break;
        case "desc":
               ...
    }
}
public static IOrderedQueryable<T> AddOrdering<T, TKey>(
this IQueryable<T> source,
Expression<Func<T, TKey>> keySelector,
bool descending)
{

// If it's not ordered yet, use OrderBy/OrderByDescending.
if(source.Expression.Type != typeof(IOrderedQueryable<T>))
{
    return descending ? source.OrderByDescending(keySelector)
                      : source.OrderBy(keySelector);
}
// Already ordered, so use ThenBy/ThenByDescending
return descending ? ((IOrderedQueryable<T>)source).ThenByDescending(keySelector)
                  : ((IOrderedQueryable<T>)source).ThenBy(keySelector);
}
foreach(var sort in sorting)
{
bool descending = sort.By == "desc";
switch (sort.Sort)
{
    case "forename":
        query = query.AddOrdering(o => o.Forename, descending);
        break;
    case "surname":
        query = query.AddOrdering(o => o.Surname, descending);
        break;
}
}