如何在Linq和EF中订购嵌套集合

时间:2014-08-22 11:03:20

标签: c# linq entity-framework frameworks entity

我想为我的数据制作一份treelistview。

树应该看起来像这样

  

帐户
   - >供应商     
- >帐户

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; }
}

我想订购我的查询。

应该像......

帐户
供应商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

感谢您的帮助! : - )

1 个答案:

答案 0 :(得分:0)

它可能有点不同的方法取决于你是否已经有一个结果集,并且只想在代码中对它进行排序,或者如果你想为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();