LINQ – Join à gauche, grouper par et compter

Disons que j’ai ce SQL:

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

Comment puis-je traduire cela en LINQ to SQL? Je me suis bloqué au COUNT (c.ChildId), le SQL généré semble toujours sortir COUNT (*). Voici ce que j’ai eu jusqu’à présent:

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

Je vous remercie!

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

Pensez à utiliser une sous-requête:

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

Si les types de requête sont connectés par une association, cela simplifie:

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

RÉPONSE TARDIVE:

Vous ne devriez pas avoir besoin de la gauche si tout ce que vous faites est Count (). Notez que join...into est en fait traduit en GroupJoin qui renvoie des regroupements comme new{parent,IEnumerable} il vous suffit donc d’appeler Count() sur le groupe:

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

Dans la méthode d’extension, la syntaxe d’une join into est équivalente à GroupJoin de GroupJoin (alors qu’une join sans into est la 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) }) 

Bien que l’idée de la syntaxe LINQ soit d’émuler la syntaxe SQL, vous ne devriez pas toujours penser à traduire directement votre code SQL dans LINQ. Dans ce cas particulier, nous n’avons pas besoin de faire de regroupement dans la mesure où l’ intégration est un groupe qui se joint à lui-même.

Voici ma solution:

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

Contrairement à la solution la plus votée ici, nous n’avons pas besoin de vérifier j1 , j2 et null dans Count (t => t.ChildId! = Null)