将平面集合转换为一对多 C#/Linq

Posted

技术标签:

【中文标题】将平面集合转换为一对多 C#/Linq【英文标题】:Convert flat collection to one-?many C#/Linq 【发布时间】:2022-01-10 00:46:00 【问题描述】:

我有一个数据集在这个类的集合中:

public class AOClientData

    public int boclient_id  get; set; 
    public string beneficialownertype_name  get; set; 
    public int account_id  get; set; 
    public string fi_name  get; set; 
    public string acct_number  get; set; 

                           

看起来像这样:

boclient_id    beneficialownertype_name   account_id     fi_name      acct_number
1001           Joe                        501            ABC          12345
1001           Joe                        502            BCA          54321
1002           Fred                       990            DDd          22334

目标是把它放入这个类的集合中:

   public class ClientInfo 
    
        public int boclient_id  get; set; 
        public string beneficialownertype_name  get; set; 
        public List<AccountInfo> Accounts  get; set; 
    
               

与这个类是一对多的关系:

public class AccountInfo 

    public int account_id  get; set; 
    public string fi_name  get; set; 
    public string acct_number  get; set; 

       

结果应该是如下所示的一组 ClientInfo 对象:

1001     Joe    501,           ABC,  12345         ,
                502,           BCA,  54321         
1002     Fred   990,         DDd,  22334      
            
            

这是我的尝试,它确实加载了所有客户端数据,但 ClientInfo.Accounts 属性中 AccountInfo 对象的属性全部为空:

        List<ClientInfo> clientInfo = aoClientData
            .GroupBy(c => new  c.boclient_id, c.beneficialownertype_name )
            .Select(xGrp => new ClientInfo
            
                boclient_id = xGrp.Key.boclient_id,
                beneficialownertype_name = xGrp.Key.beneficialownertype_name,
                Accounts = xGrp
                    .Select(c => new AccountInfo
                    
                        account_id = c.account_id,
                        fi_name = c.fi_name,
                        acct_number = c.acct_number
                    )
                    .ToList()
            )
            .ToList();
                            

LINQ 出了什么问题?

【问题讨论】:

【参考方案1】:

您已将 c 变量重新用作您的 aoCLientData 项目和分组项目。在您的内部选择中使用.Select(a =&gt; new AccountInfo...,然后使用a 而不是c 来选择a.account_ida.fi_namea.acct_number

var result = data
    .GroupBy(x => new  x.boclient_id, x.beneficialownertype_name )
    .Select(x => 
        new ClientInfo
        
            boclient_id = x.Key.boclient_id,
            beneficialownertype_name = x.Key.beneficialownertype_name,
            Accounts = x.Select(a =>
                new AccountInfo 
                
                    account_id = a.account_id,
                    fi_name = a.fi_name,
                    acct_number = a.acct_number
                ).ToList()
        );

【讨论】:

非常感谢,但我得到的结果与最初描述的相同 - Carl 这不是问题的原因。 GroupBy中的参数c不会干扰Select中的参数c【参考方案2】:

如果我查看您的代码,我不明白为什么您会得到多个ClientInfos,每个属性Accounts 都有一个null 值。我什至不希望有一个空的帐户列表。

您是否尝试过使用带有参数 resultSelector 的overload of GroupBy?

List<ClientInfo> clientInfo = aoClientData
    .GroupBy(

    // parameter keySelector:
    clientInfo => new
    
        BoClientId = clientInfo.boclient_id,
        BeneficialOwnerTypeName = clientInfo.beneficialownertype_name,
    )

    // parameter resultSelector: for every key item with all its zero or more AOClientData
    // make one new ClientInfo
    (key, aoClientsWithThisKey) => new ClientInfo
    
        boclient_id = key.BoClientId,
        beneficialownertype_name = key.BeneficialOwnerTypeName,
        Accounts = aoClientsWithThisKey.Select(aoClient => new AccountInfo
        
            account_id = aoClient.account_id,
            fi_name = aoClient.fi_name,
            acct_number = aoClient.acct_number
        )
        .ToList(),
    )
    .ToList();

【讨论】:

谢谢,但恐怕这也不起作用【参考方案3】:

解决办法如下:

var items = aoClientData.GroupBy(c => new  c.boclient_id, c.beneficialownertype_name )
    .Select(grp => new ClientInfo()
    
        boclient_id = grp.Key.boclient_id,
        beneficialownertype_name = grp.Key.beneficialownertype_name,                            
    Accounts = grp.Select(r => new AccountInfo() 
     
        account_id = r.account_id,
        acct_number = r.acct_number
    ).ToList()
).ToList();

【讨论】:

以上是关于将平面集合转换为一对多 C#/Linq的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ 和 EF Core 进行一对多

LINQ 如何在一对多连接中指定选择某些列

.NET Linq 查询一对多关系

MyBatis一对多映射

Linq-To-Sql ORM 更新一对多

Linq一对多联合查询