views:

159

answers:

1

I have the following objects. An IEnumerable<Agency> Agencies, which then contains BusinessUnits and BusinessUnits contain clients:

public class Agency  
{   
    public int ID; 
    public IEnumerable<BusinessUnit> BusinessUnits;  
}  

public class BusinessUnit
{
    public string Name;  
    public int ID;  
    public decimal AmountSpent;
    public IEnumerable<Client> Clients;  
}

public class Client
{
    public string Name;  
    public int ID;  
    public decimal AmountSpent;
}

I've been using this query to consolidate my BusinessUnits under the agencies so I can display an "All Agencies:" my data goes from this:

Agency1
++BusinessUnit1 - $20
++++Client1 - $10
++++Client2 - $10

Agency2
++BusinessUnit2 - $20
++++Client1 - $20

Agency3
++BusinessUnit1 - $10
++++Client5 - $5
++++Client6 - $5
++BusinessUnit2 - $25
++++Client1 - $25

to this:

All Agencies
++BusinessUnit1 - $30
++++Client1 - $10
++++Client2 - $10
++++Client5 - $5
++++Client6 - $5

++BusinessUnit2 - $45
++++Client1 - $20
++++Client1 - $25

I've been using the following LINQ query to do so:

var groupings =
    from agency in agencies
    from businessUnit in agency.BusinessUnits
    from client in businessUnit.Clients
    group client by businessUnit.ID into clients
    select clients;

var businessUnits =
    from grouping in groupings
    select new
    {
        ID = grouping.Key,
        AmountSpent = grouping.Sum(client => client.AmountSpent),
        Clients = grouping
    };

Console.WriteLine("All Agencies");

foreach (var businessUnit in businessUnits)
{
    Console.WriteLine("++BusinessUnit{0} - ${1}",
                      businessUnit.ID,
                      businessUnit.AmountSpent);

    foreach (var client in businessUnit.Clients)
    {
        Console.WriteLine("++++Client{0} - ${1}", client.ID, client.AmountSpent);
    }
}

My question is: How do I also include BusinessUnit and Client's "Name" field in the returned objects. As of right now, my resulting BusinessUnits only contain their ID which they get from the key of the grouping.

I need to also be able to return "Name" from the BusinessUnit in my query, not just its ID. I'm not sure how to do this with LINQ in conjunction with Groupings.

+2  A: 

You could change the grouping key - this assumes that there won't be multiple names for the same ID or vice versa:

var groupings =
    from agency in agencies
    from businessUnit in agency.BusinessUnits
    from client in businessUnit.Clients
    group client by new { businessUnit.ID, businessUnit.Name } into clients
    select clients;

var businessUnits =
    from grouping in groupings
    select new
    {
        ID = grouping.Key.ID,
        Name = grouping.Key.Name,
        AmountSpent = grouping.Sum(client => client.AmountSpent),
        Clients = grouping
    };
Jon Skeet
@Jon Skeet, what if the BusinessUnit class grows to contain other fields? Is adding them to the key viable?
KingNestor
That depends on whether the extra data affects the uniqueness.
Jon Skeet