如何在 linq 中使用自定义列值对列表进行排序?

How to sort List using custom column values in linq?

Net 核心、Ef 核心和 linq。我有 table 列状态。它包含值 New、In-Progress 和 closed。当我查询所有带有 New 的行时,应该首先出现,然后是进行中和关闭。下面是我的代码。

var Requests = await this.RequestRepository.GetAsync(x => x.IsActive == true && x.CreatedBy == LoggedInUser, null, x => x.Country).ConfigureAwait(false);

下面是我的 GetAsync 方法

public async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, params Expression<Func<T, object>>[] includes)
        {
            IQueryable<T> query = this.dbSet;
            foreach (Expression<Func<T, object>> include in includes)
            {
                query = query.Include(include);
            }

            if (filter != null)
            {
                query = query.Where(filter);
            }

            if (orderBy != null)
            {
                query = orderBy(query);
            }

            return await query.ToListAsync().ConfigureAwait(false);
        } 

所以我希望所有状态为 New 的行应该先出现,然后是 In-Progress 并关闭。无论如何我都找不到弄清楚。有人可以帮我写这个吗。任何帮助,将不胜感激。谢谢

我已经按照您的要求制作了示例代码。它在我身上运行良好。请参考这个。希望这也适用于您的代码。

using System;
using System.Collections.Generic;
using System.Linq;

namespace Test
{
    public class Program
    {
        public static void Main(string[] args)
        {
            List<Name> list = new List<Name>
            {
                new Name { FirstName = "Nishan1", LastName = "Dhungana1", Status = Status.Closed},
                new Name { FirstName = "Nishan2", LastName = "Dhungana2", Status = Status.New},
                new Name { FirstName = "Nishan3", LastName = "Dhungana3", Status = Status.New},
                new Name { FirstName = "Nishan4", LastName = "Dhungana4", Status = Status.Closed},
                new Name { FirstName = "Nishan5", LastName = "Dhungana5", Status = Status.Closed},
                new Name { FirstName = "Nishan6", LastName = "Dhungana6", Status = Status.InProgress},
                new Name { FirstName = "Nishan7", LastName = "Dhungana7", Status = Status.Closed},
                new Name { FirstName = "Nishan8", LastName = "Dhungana8", Status = Status.InProgress},
                new Name { FirstName = "Nishan9", LastName = "Dhungana9", Status = Status.InProgress},
                new Name { FirstName = "Nishan10", LastName = "Dhungana10", Status = Status.New},
                new Name { FirstName = "Nishan11", LastName = "Dhungana11", Status = Status.New}
            };

            list = list.OrderByDescending(x => x.Status == Status.New)
                .ThenByDescending(x => x.Status == Status.InProgress)
                .ThenByDescending(x => x.Status == Status.Closed)
                .ToList();

            Console.WriteLine("hey");
            Console.ReadLine();
        }
    }

    public class Name
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Status Status { get; set; }
    }

    public enum Status
    {
        New = 1,
        InProgress = 2,
        Closed = 3
    }
}

如果您抛弃这个“辅助”方法而直接使用 LINQ,您的生活可能会轻松很多。看看它的可读性有多明显:

var apps = db.FundingApplications
  .Include(x => x.Applicant)
  .Where(x => x.ApplicationDate.Year == DateTime.Now.Year)
  .OrderBy(x => (int)x.Status)

(为了简洁,我跳过了 await/async,并不是因为我提倡同步)

状态当然是枚举,如:

enum Status{
  New, Inprogress, Closed
}

如果你的枚举不是像这样的数字顺序而是 eg

enum Status {
  New = 20,
  InProgress = 1,
  Closed = 99
}

然后您可以在 ToString 之后通过降序对其进行排序(您会注意到名称的字母顺序相反)或使用映射例如 d[New] = 0, d[InProgress] = 1 ... 的字典创建映射,或者执行(在-line) 如果在 OrderBy 中设置。

OrderByDescending(x => x.Status.ToString("g"));

var d = new Dictionary<status, int>() {
  {New, 0}, {InProg,1}, {Closed,2}
};
OrderBy(x => d[x.Status]);

OrderBy(x => x.Status == Status.New ? 0 : (x.Status == Status.InProg ? 1 : 2))

不过只有最后一个有真正的机会在服务器上执行,并且只有在您不重命名它们或添加破坏顺序的新名称时,按名称排序才有效。

我也很欣赏另一个答案中给出的 OrderBy/ThenBy 并认为它很好,但我认为应该注意测试它是在服务器上还是在客户端上执行,因为它执行布尔比较和许多数据库不使用布尔值作为数据类型,或者如果他们这样做,他们可能会在 true (1)

之前排序 falsy (0)
OrderBy(x => x.Status == New)

可能就是这样,它将所有已关闭的和 InProg 排在 New 之前,因为如果服务器评估的布尔值的结果是 InProg/closed 的 0 和 new 的 1。 MySql 和 Postgres 将是我的首选,因为我担心这会被服务器评估,因为它们确实允许在其他数据库不允许的上下文中使用布尔类型值。

因此,请注意 a) 这种排序正在评估您期望和想要的位置 (client/server) 和 b) 如果它确实在服务器上评估,那么服务器会按照您的需要进行排序


编辑,刚刚看到您的评论表明 Status 不是枚举而是一组字符串常量??

如果您的数据库值实际上是字符串并且状态从来都不是枚举,那么您可以按降序排列它们

OrderByDescending(x => x.Status)