如何在 Linq 和 EF 中对嵌套集合进行排序

本文关键字:集合 嵌套 排序 Linq EF | 更新日期: 2023-09-27 18:19:14

我想为我的数据制作一个树状列表视图。

树应该看起来像这样

帐户
->供应商
->账户

public sealed class AccountRoot    
{
    public AccountRoot()
    {
        Providers = new Collection<Hoster>();
    }
    public long AccountRootId { get; set; }
    public ICollection<Hoster> Providers { get; set; } 
}
public sealed class Hoster
{
    public Hoster()
    {
        Accounts = new Collection<Account>();
    }
    [Key]
    public long HosterId { get; set; }
    public long AccountRootId { get; set; }
    public string Name { get; set; }
    public ICollection<Account> Accounts { get; set; } 
}
public sealed class Account
{
    [Key]
    public long AccountId { get; set; }
    public long HosterId { get; set; }
    public Hoster Hoster { get; set; }
    public string Name { get; set; }
}

我想订购我的查询。

应该是像 sth 一样

帐户
提供商 A-Z
账户 A-Z

直到现在我得到的是..

var query = _entity.AccountRoot.Local
                   .Select(x => new AccountRoot()
                   {
                        AccountRootId = x.AccountRootId,
                        Providers = x.Providers.OrderBy(y => y.Name).ToList()
                   }).ToList();

缺少的是下一个嵌套集合的orderby

谢谢你的帮助! :-(

如何在 Linq 和 EF 中对嵌套集合进行排序

根据你是否已经有一个结果集,并且只想在代码中对其进行排序,或者是否想要为 EF 构造IQueryable<>,该方法将成功编译为 SQL 并在数据库中使用实际排序执行,这可能是一些不同的方法。

首先,假设你已经在代码中拥有集合。在这种情况下,你有对象AccountRoot,它包含Providers的集合,每个集合都有Accounts的集合。显然,您不能返回相同的对象,因为您需要对集合属性重新排序,因此您只需要构造新的对象。我只会对集合进行排序,但如果需要,您可以构建全新的实体:

var query = ...
    .Select(x => new AccountRoot
    {
        // add copy properties here
        // ....
        Providers = x.Providers
                        .Select(y =>
                        {
                            // Here we can construct completely new entity, 
                            // with copying all properties one by one,
                            // or just reorder existing collection as I do here
                            var result = y;
                            result.Accounts = y.Accounts.OrderBy(z => z.Name).ToArray();
                            return result;
                        })
                        .OrderBy(y => y.Name)
                        .ToArray()
    })
    .ToArray();

第二种情况,如果您需要直接从SQL获取它,则有点不同,因为您不能在lambda中使用所有var result = ...; ... return result的东西 - 它不会编译为SQL。但想法是一样的 - 你需要从数据集构建投影。它应该是这样的:

var query = ...
    .Select(x => new AccountRoot
    {
        AccountRootId = x.AccountRootId,
        // Other properties to copy
        // ...
        Providers = x.Providers
                        .Select(y => new Hoster
                        {
                            HosterId = y.HosterId,
                            // Other properties to copy
                            // ...
                            Accounts = y.Accounts.OrderBy(z => z.Name).ToArray(),
                        })
                        .OrderBy(y => y.Name)
                        .ToArray()
    })
    .ToArray();