LINQ-Left Join, Group By, and Count

Powiedzmy, że mam ten SQL:

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

Jak mogę to przetłumaczyć na LINQ na SQL? Utknąłem w liczniku (C. ChildId), wygenerowany SQL zawsze wydaje się wypisywać COUNT (*). Oto co mam do tej pory:

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() }
Dziękuję!
Author: Mehrdad Afshari, 2009-03-30

5 answers

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) }
 181
Author: Mehrdad Afshari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-29 22:28:29

Rozważ użycie subquery:

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

Jeśli typy zapytań są połączone asocjacją, upraszcza się to do:

from p in context.ParentTable 
let cCount = p.Children.Count()
select new { ParentId = p.Key, Count = cCount } ;
 55
Author: Amy B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-17 04:26:47

PÓŹNA ODPOWIEDŹ:

You shouldn 't need the left join at all if you' re doing is Count (). Zauważ, że join...into jest faktycznie przetłumaczone na GroupJoin, które zwraca grupy jak new{parent,IEnumerable<child>}, więc wystarczy wywołać Count() na grupie:

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

W składni metody rozszerzenia a join into jest równoważne GroupJoin (podczas gdy a join bez into jest Join):

context.ParentTable
    .GroupJoin(
                   inner: context.ChildTable
        outerKeySelector: parent => parent.ParentId,
        innerKeySelector: child => child.ParentId,
          resultSelector: (parent, children) => new { parent.Id, Count = children.Count() }
    );
 31
Author: Eren Ersönmez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-02 10:00:22
 (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) })
 7
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-14 08:49:12

Podczas gdy ideą składni LINQ jest emulowanie składni SQL, nie zawsze powinieneś myśleć o bezpośrednim tłumaczeniu kodu SQL na LINQ. W tym konkretnym przypadku, nie musimy robić group into Ponieważ join into jest połączeniem grupowym.

Oto moje rozwiązanie:

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

W przeciwieństwie do najczęściej głosowanego rozwiązania tutaj, nie potrzebujemy j1, j2 and null checking in Count (t = > T. ChildId != null)

 6
Author: Mosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-01 04:44:38