I have 2 model objects, DriverDetailsSourceObject which is meant to be for holding the DriverDetailsAPI response and DriverDetailsView which is used to show DriverDetails details with aggregated values on the web page.
public class DriverDetailsSourceObject
{
public string Name { get; set; }
public string GroupName { get; set; }
public DateTime DateOfPurchase { get; set; }
}
public class DriverDetailsView
{
public string Name { get; set; }
public string GroupName { get; set; }
public DateTime DateOfPurchase { get; set; }
public int Count { get; set; } = 1;
public DriverDetailsView(DriverDetailsSourceObject source)
{
Name = source.Name;
GroupName = source.GroupName;
DateOfPurchase = source.DateOfPurchase;
}
}
DriverDetailsView is used on multiple pages. In 2 of them, Name, GroupName, DateOfPurchase and Count is shown where Count is always 1 and ToTalCount will be the number of DriverDetailsView objects in the collection.
| Name | Count | Group Name | Date |
|---|---|---|---|
| RoadAssistance A | 1 | Group A | 1/1/2022 |
| RoadAssistance A | 1 | Group B | 2/1/2022 |
| RoadAssistance A | 1 | Group A | 2/2/2022 |
| RoadAssistance B | 1 | Group A | 2/2/2022 |
| Total | 4 |
In one of the pages, we need to show all the objects grouped by Name and calculate Count and list of GroupNames. I used the following LINQ expression.
private IEnumerable<DriverDetailsSourceObject> DriverDetails { get; set; } = Enumerable.Empty<DriverDetailsSourceObject>();
private IEnumerable<DriverDetailsView> DriverDetailsByOption { get; set; } = Enumerable.Empty<DriverDetailsView>();
.
.
DriverDetails = DriverService.GetDriverOptions(brandName, isAgentLoggedIn);
DriverDetailsByOption = DriverDetails.GroupBy(o => o.Name)
.Select(d =>
new DriverDetailsSourceObject()
{
Name = d.First().Name,
GroupName = d.First().GroupName,
Count = d.Count()
})
.Select(v => new DriverDetailsView(v));
I am not getting the correct result using the above LINQ. Count is always 1 even after being grouped by Name. It could be because the Count has a default value 1 in DriverDetailsView, which I cannot change as it is used by other pages.
| Name | Count | Group Name |
|---|---|---|
| RoadAssistance A | 1 | Group A |
| RoadAssistance B | 1 | Group A |
| Total | 2 |
Expected result is given below:
| Name | Count | Group Name |
|---|---|---|
| RoadAssistance A | 3 | Group A, Group B |
| RoadAssistance B | 1 | Group A |
| Total | 4 |
How do I change my LINQ expression to get this result?
CodePudding user response:
Issue 1: As you didn't initialize the Count in DriverDetailsView's constructor, the Count will be 1 by default as initialized.
And meanwhile, you mention that the DriverDetailsSourceObject which is your API response class doesn't have the Count property.
Issue 2:
In your LINQ statement, you return the first GroupName instead of multiple GroupName:
GroupName = d.First().GroupName
Solution
For Issue 1:
I would suggest using an empty constructor instead of the DriverDetailsView(DriverDetailsSourceObject source) constructor.
public class DriverDetailsView
{
...
public DriverDetailsView() { }
...
}
For Issue 2:
To return multiple GroupName, you need to select and distinct GroupName, next use String.Join() to join the GroupName array as string.
Change the LINQ statement as below:
DriverDetailsByOption = DriverDetails.GroupBy(o => o.Name)
.Select(d => new DriverDetailsView
{
Name = d.Key,
GroupName = String.Join(",", d.Select(x => x.GroupName).Distinct()),
Count = d.Count()
});
As you .GroupBy() Name, this line
Name = d.First().Name
can be replaced with:
Name = d.Key
