Home > Software design >  Convert flat collection to one-?many C#/Linq
Convert flat collection to one-?many C#/Linq

Time:12-05

I have a data set that is in a collection of this class:

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

and looks like this:

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

The goal is to get it into a collection of this class:

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

which is in a one-to-many relationship with this class:

public class AccountInfo 
{
    public int account_id { get; set; }
    public string fi_name { get; set; }
    public string acct_number { get; set; }
}
       

The result should be a collection of ClientInfo objects looking like this:

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

Here is my attempt which does load all the client data but the properties of the AccountInfo object in the ClientInfo.Accounts property are all null:

        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();
                            

What is wrong with the LINQ?

CodePudding user response:

You have reused the c variable to be both your aoCLientData items as well as your grouped items. In your inner select use .Select(a => new AccountInfo... and then use a instead of c to select the a.account_id, a.fi_name and a.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()
        });

CodePudding user response:

If I look at your code, I can't see why you would get several ClientInfos, each with a null value for property Accounts. I wouldn't even expect an empty Accounts list.

Have you tried to use the overload of GroupBy that has a parameter resultSelector?

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();
  • Related