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