Search code examples
c#linqrazor

Select properties (inner SELECT) in LINQ with GroupBy


I have a list of events which are unique based on their eventId and start/end times but otherwise they are the same. So for example, my dataItem looks like this...

eventItem.EventId
eventItem.EventTypeId
eventItem.StartDateTime 
eventItem.EndDateTime
eventItem.Available
eventItem.ShowSystemName

and my dataset looks like this...

408277 110 5/26/2021 3:00:00 PM 5/26/2021 3:45:00 PM 100 Event 1 
408551 109 5/26/2021 4:00:00 PM 5/26/2021 4:45:00 PM 100 Event 2 
408124 110 5/27/2021 10:30:00 AM 5/27/2021 11:15:00 AM 100 Event 1 
408398 109 5/27/2021 11:30:00 AM 5/27/2021 12:15:00 PM 100 Event 2 
408201 110 5/27/2021 1:00:00 PM 5/27/2021 1:45:00 PM 100 Event 1 
408475 109 5/27/2021 2:00:00 PM 5/27/2021 2:45:00 PM 100 Event 2 
408278 110 5/27/2021 3:00:00 PM 5/27/2021 3:45:00 PM 100 Event 1 
408552 109 5/27/2021 4:00:00 PM 5/27/2021 4:45:00 PM 100 Event 2

My desired query from that data would return each unique event only once (based on ShowSystemName) and then a list of subitems for that event. Something like..

Event 1
    408277 110 5/26/2021 3:00:00 PM 5/26/2021 3:45:00 PM
    408124 110 5/27/2021 10:30:00 AM 5/27/2021 11:15:00 AM 
    408201 110 5/27/2021 1:00:00 PM 5/27/2021 1:45:00 PM
    408278 110 5/27/2021 3:00:00 PM 5/27/2021 3:45:00 PM
 
Event 2
    408398 109 5/27/2021 11:30:00 AM 5/27/2021 12:15:00 PM
    408475 109 5/27/2021 2:00:00 PM 5/27/2021 2:45:00 PM 
    408552 109 5/27/2021 4:00:00 PM 5/27/2021 4:45:00 PM
    408551 109 5/26/2021 4:00:00 PM 5/26/2021 4:45:00 PM 

I have started out with

foreach(var eventItem in result.Events.GroupBy(x => x.ShowSystemName).Select(x => x.First()))
{
    ...
}

which gets me each event only once as expected, but I am struggling with doing an inner select.

I am working in Razor because ultimately this will be rendered as HTML, but since the server call for the events is my code as well, I could move this logic into the service call if that buys me anything.

Thanks!


Solution

  • GroupBy() will not return event items but groups of event items. Specifically it's an IEnumerable of IGrouping<TKey, TElement>s where TKey is the type of what you grouped by (a string) and TElement is your event class.

    You can access the common key of a group with the IGrouping<TKey, TElement>.Key property and you can also iterate over each group with foreach.

    Hence a nested loop should get you the expected output:

    foreach (var eventGroup in result.Events.GroupBy(x => x.ShowSystemName))
    {
        Console.WriteLine(eventGroup.Key);
    
        foreach (var eventItem in eventGroup)
        {
            Console.WriteLine($"\t{eventItem.EventId} {eventItem.EventTypeId} ...")
        }
    }