LINQ – Junção Esquerda, Agrupar por e Contagem

Vamos dizer que eu tenho esse SQL:

SELECT p.ParentId, COUNT(c.ChildId) FROM ParentTable p LEFT OUTER JOIN ChildTable c ON p.ParentId = c.ChildParentId GROUP BY p.ParentId 

Como posso traduzir isso para o LINQ to SQL? Eu fiquei preso no COUNT (c.ChildId), o SQL gerado sempre parece produzir COUNT (*). Aqui está o que eu tenho até agora:

 from p in context.ParentTable join c in context.ChildTable on p.ParentId equals c.ChildParentId into j1 from j2 in j1.DefaultIfEmpty() group j2 by p.ParentId into grouped select new { ParentId = grouped.Key, Count = grouped.Count() } 

Obrigado!

 from p in context.ParentTable join c in context.ChildTable on p.ParentId equals c.ChildParentId into j1 from j2 in j1.DefaultIfEmpty() group j2 by p.ParentId into grouped select new { ParentId = grouped.Key, Count = grouped.Count(t=>t.ChildId != null) } 

Considere o uso de uma subconsulta:

 from p in context.ParentTable let cCount = ( from c in context.ChildTable where p.ParentId == c.ChildParentId select c ).Count() select new { ParentId = p.Key, Count = cCount } ; 

Se os tipos de consulta estiverem conectados por uma associação, isso simplifica para:

 from p in context.ParentTable let cCount = p.Children.Count() select new { ParentId = p.Key, Count = cCount } ; 

RESPOSTA ATRASADA:

Você não deve precisar da junit à esquerda se tudo que você está fazendo é Count (). Note que join...into é realmente traduzido para GroupJoin que retorna agrupamentos como new{parent,IEnumerable} então você só precisa chamar Count() no grupo:

 from p in context.ParentTable join c in context.ChildTable on p.ParentId equals c.ChildParentId into g select new { ParentId = p.Id, Count = g.Count() } 

Na syntax do método de extensão, uma join into é equivalente a GroupJoin (enquanto uma join sem um into é Join ):

 context.ParentTable .GroupJoin( inner: context.ChildTable outerKeySelector: parent => parent.ParentId, innerKeySelector: child => child.ParentId, resultSelector: (parent, children) => new { parent.Id, Count = children.Count() } ); 
  (from p in context.ParentTable join c in context.ChildTable on p.ParentId equals c.ChildParentId into j1 from j2 in j1.DefaultIfEmpty() select new { ParentId = p.ParentId, ChildId = j2==null? 0 : 1 }) .GroupBy(o=>o.ParentId) .Select(o=>new { ParentId = o.key, Count = o.Sum(p=>p.ChildId) }) 

Embora a ideia por trás da syntax LINQ seja emular a syntax SQL, você não deve sempre pensar em traduzir diretamente seu código SQL para o LINQ. Neste caso em particular, não precisamos fazer um grupo em que o join é um grupo que se une a si mesmo.

Aqui está minha solução:

 from p in context.ParentTable join c in context.ChildTable on p.ParentId equals c.ChildParentId into joined select new { ParentId = p.ParentId, Count = joined.Count() } 

Ao contrário da solução mais votada aqui, não precisamos de j1 , j2 e verificação nula em Count (t => t.ChildId! = Null)