Search code examples
c#linqlambdaiqueryablelinq-group

Lambda Linq Iqueryable group - add another grouping


I have a method that I use for generating a summary report, based on the options a user selects in pick lists, to count the number of a type of test that is completed in a region, with subset locations, within a date range.

Here's what the data looks like: Completed Test Counts by Location From 1 FEB 2015 to 1 MAR 2015

Total  TestType  Location  Region  Division
455    24 Hour   Lab 1     City 1  Division A
28     24 Hour   Lab 2     City 1  Division A
95     24 Hour   Clinic Z  City 2  Division A
189    24 Hour   Clinic Y  City 2  Division A

Here's what it might look like for a different test type, at the same time period:

Total  TestType  Location  Region  Division
285    48 Hour   Lab 1     City 1  Division A
12     48 Hour   Lab 2     City 1  Division A
75     48 Hour   Clinic Z  City 2  Division A
106    48 Hour   Clinic Y  City 2  Division A

Now, the users would like to see the summary breakdown by testType in one report (in SQL, adding another attribute to a group by). In my pick list of testTypeId, I am using 0 as my "All" item. In a perfect world, I'd have another addition to the IQueryable if testTypeId == 0, so that I can keep the same private method, rather than writing a new query.

Here's what we'd like the data to look like in the "ALL" situation:

Total  TestType  Location  Region  Division
455    24 Hour   Lab 1     City 1  Division A
285    48 Hour   Lab 1     City 1  Division A
59     12 Lead   Lab 1     City 1  Division A
28     24 Hour   Lab 2     City 1  Division A
12     48 Hour   Lab 2     City 1  Division A
95     24 Hour   Clinic Z  City 2  Division A
75     48 Hour   Clinic Z  City 2  Division A
5      12 Lead   Clinic Z  City 2  Division A
189    24 Hour   Clinic Y  City 2  Division A
106    48 Hour   Clinic Y  City 2  Division A
8      12 Lead   Clinic Y  City 2  Division A

The example below shows what I have with what I'd like to add in it, but the syntax tells me I can't take an IQueryable containing an IGrouping and convert it to the target type of IQueryable.

Can anyone point me in a good direction here?

private CompletedCountReport GetCompletedCountsByRegion(int regionId, DateTime? startDate, DateTime? endDate, int testTypeId)
{
    var ccRpt = new CompletedCountReport { CompletedCounts = new List<CompletedCount>(), StartDate = startDate, EndDate = endDate, SelectedRegionID = regionId};

    var query = HolterTestDao.FindAll(new GetCompletedByRegionIdAndDates(regionId, startDate.Value, endDate.Value));

    // a specific test type was selected
    if (testTypeId > 0)
    {
        query = query.Where(x => x.HolterTestType == testTypeId);
    }
    // THIS IS WHAT I WANT TO ADD -> otherwise group by test type  <-  THIS IS WHAT I WANT TO ADD.
    if (testTypeId == 0)
    {
        query = query.GroupBy(x => x.HolterTestType);
    }
    // order by locationID within the region.
    query = query.OrderBy(x => x.Location.ID);

    var htList = query.ToList();

    // now Group by Location, to get counts. 
    var reportContents = htList.GroupBy(x => x.Location.ID);
    foreach (var r in reportContents)
    {
        var rList = r.ToList();

        var cc = new CompletedCount();
        var loc = LocationDao.FindById(r.Key);
        cc.Description = loc.Description;
        cc.RegionId = loc.Region.ID;
        cc.DivisionId = loc.Region.Division.ID;
        cc.TestTypeId = testTypeId;
        cc.Count = rList.Count;
        ccRpt.CompletedCounts.Add(cc);
    }

    return ccRpt;
}

Solution

  • My solution was to OrderBy Location and HolterTestType, then GroupBy location for the basic contents, and then add another grouping in my loop through the results to get the counts by test type:

            query = query.OrderBy(x => x.Location.ID).ThenBy(x => x.HolterTestType);
            var htList = query.ToList();
    
            // now Group by Location. 
            var reportContents = htList.GroupBy(x => x.Location.ID);
    
            foreach (var r in reportContents)
            {
                //Group by TestType, to get counts.
                var t = r.GroupBy(x => x.HolterTestType);
                var tList = t.ToList();
    
                foreach(var u in tList)
                {
                    var cc = new CompletedCount();
                    var loc = LocationDao.FindById(r.Key);
                    cc.Description = loc.Description;
                    cc.RegionId = loc.Region.ID;
                    cc.DivisionId = loc.Region.Division.ID;
                    cc.TestTypeId = u.Key;
                    cc.Count = u.Count();
                    ccRpt.CompletedCounts.Add(cc);
                }
            }