Группировка Linq по и количество

Я пытаюсь понять, как groupy by and count работает с linq, но я не могу понять, как делать то, что я хочу.

У меня есть эта таблица:

ASSET:
Id, Code, Name, ParentId

ParentId имеет значение null, если это корень, и содержит родительский идентификатор, если актив связан с другим активом.

Я хотел бы иметь для каждого корневого родителя идентификатор и количество детей

это запрос, который я использовал:

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

это запрос linq, который я делаю

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() };

но объект генерирует этот запрос:

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]

проблема исходит от COUNT(1), как я могу сказать, что это должно быть COUNT(children.Id)


person dco    schedule 16.07.2014    source источник
comment
COUNT(1) — это то же самое, что и COUNT(children.Id) в исходном SQL-запросе. Фактически, COUNT(1) будет работать немного быстрее, чем COUNT(children.Id), так как это статическое значение.   -  person entropic    schedule 16.07.2014
comment
В этом случае, когда у меня нет дочерних элементов для актива, когда я использую COUNTchildren.Id), он возвращает 0, но с COUNT(1) у меня всегда есть как минимум 1   -  person dco    schedule 16.07.2014
comment
Должен любить эти ценности NULL..   -  person entropic    schedule 16.07.2014


Ответы (2)


Поскольку вы хотите иметь дело со значениями NULL в children.Id, вам понадобится способ их подсчета при выборе окончательного объекта. Для этого вы должны сгруппировать в новый объект, к которому вы могли бы запросить, чтобы получить правильный счет. Вот измененный объект запроса, который вы ищете:

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) };

Я использовал следующую скрипту С#, чтобы протестировать ее, и она правильно возвращает 0 записей, если у родителя нет детей.

https://dotnetfiddle.net/gyqpef

person entropic    schedule 16.07.2014

Вы можете попробовать что-то вроде этого:

// 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() });
person Christos    schedule 16.07.2014