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

3

我想为我的数据创建一个树形列表视图。

树应该长这样

账户
-> 提供者
-> 账户

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。感谢您的帮助! :-)

你为什么要从Local中选择? - Yuliam Chandra
我的实体是单例的,因为我需要它用于列表...尝试过使用短暂实体,但对我的目的没有起作用...谢谢! - DMill
你需要一个单一的查询来实现最终结果吗?还是你只需要对预先填充的对象(LocaleObservableCollection)进行排序来实现最终结果? - Yuliam Chandra
1个回答

0

根据您是否已经有结果集并希望仅在代码中进行排序,或者是否要构建可以成功编译为SQL并在数据库中实际排序的IQueryable<>来看,方法可能会有所不同。

首先,假设您已经在代码中拥有了该集合。在这种情况下,您拥有对象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();

完美答案!它按照我想要的方式工作。我选择了第二个,因为我需要直接使用它 :-) 谢谢! - DMill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接