Reputation: 327
I'm trying to understand how groupy by and count works with linq but i can't get how to do what i want.
I have this table:
ASSET:
Id, Code, Name, ParentId
the ParentId is null if its the root, and contains the parent id if the asset is linked to another asset
I'd like to have for each root parents the Id and the number of children
this is the query i used:
select father.Id, father.Code, COUNT(children.Id) As NumberOfChildren
from Asset father
left join Asset children on(father.Id = children.ParentId)
where father.ParentId IS NULL
group by father.Id, father.Code
this is the linq query i do
var query = from father in this.assetService.GetAll()
join children in this.assetService.GetAll()
on father.Id equals children.ParentId into Children
from children in Children.DefaultIfEmpty()
where father.ParentId.Value == null
group father by new { id = father.Id, code = father.Code } into gf
select new { id = gf.Key.id, count = gf.Count() };
but entity generates that query:
SELECT
1 AS [C1],
[GroupBy1].[K1] AS [Id],
[GroupBy1].[A1] AS [C2]
FROM ( SELECT
[Extent1].[Id] AS [K1],
[Extent1].[Code] AS [K2],
COUNT(1) AS [A1]
FROM [dbo].[Asset] AS [Extent1]
LEFT OUTER JOIN [dbo].[Asset] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ParentId]
WHERE [Extent1].[ParentId] IS NULL
GROUP BY [Extent1].[Id], [Extent1].[Code]
) AS [GroupBy1]
the issue comes from the COUNT(1)
, how can i tell thats its supposed to be COUNT(children.Id)
Upvotes: 0
Views: 1715
Reputation: 1683
Since you want to deal with the NULL
values in children.Id
, you'll need a way to count them when you are selecting your final object. To do this, you would group into a new object that you could query against in order to get the right count. Here's the modified query object you're looking for:
var query = from father in this.assetService.GetAll()
join children in this.assetService.GetAll()
on father.Id equals children.ParentId into Children
from children in Children.DefaultIfEmpty()
where father.ParentId.Value == null
group new { father = father, childExists = (children != null) } by new { id = father.Id, code = father.Code } into gf
select new { id = gf.Key.id, count = gf.Count(o => o.childExists) };
I used the following C# fiddle to test it, and it correctly returns 0 records if a parent has no children.
https://dotnetfiddle.net/gyqpef
Upvotes: 0
Reputation: 53958
You could try something like this:
// Get all the assets in a list.
var assets = this.assetService.GetAll().ToList();
// Get the parents.
var parents = (from asset in assets
where asset.ParentId == null);
// Remove parents from the original list.
var children = assets.RemoveAll(x => parents.Contains(x));
// Group the children by their parentId
var result = children.GroupBy(x => x.ParentId)
.Select(x => new { ParentId = x.Key, Count = x.Count() });
Upvotes: 2