c# - studio - linq to sql vs entity framework
LINQ-Unir, agrupar y contar (5)
Digamos que tengo este SQL:
SELECT p.ParentId, COUNT(c.ChildId)
FROM ParentTable p
LEFT OUTER JOIN ChildTable c ON p.ParentId = c.ChildParentId
GROUP BY p.ParentId
¿Cómo puedo traducir esto a LINQ to SQL? Me quedé atrapado en el COUNT (c.ChildId), el SQL generado siempre parece dar como resultado COUNT (*). Esto es lo que obtuve hasta ahora:
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() }
¡Gracias!
Considera usar una 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 } ;
Si los tipos de consulta están conectados por una asociación, esto se simplifica a:
from p in context.ParentTable
let cCount = p.Children.Count()
select new { ParentId = p.Key, Count = cCount } ;
Si bien la idea detrás de la sintaxis LINQ es emular la sintaxis de SQL, no siempre se debe pensar en traducir directamente su código SQL a LINQ. En este caso particular, no es necesario agruparnos porque join es un join de grupo.
Aquí está mi solución:
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() }
A diferencia de la solución más votado aquí, no necesitamos j1 , j2 y comprobación nula en Count (t => t.ChildId! = Null)
RESPUESTA TARDÍA:
No deberías necesitar la combinación izquierda si todo lo que haces es Count (). Tenga en cuenta que join...into
se traduce realmente a GroupJoin
que devuelve agrupaciones como new{parent,IEnumerable<child>}
por lo que solo necesita llamar a Count()
en el 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() }
En la sintaxis del método de extensión, una join into
es equivalente a la GroupJoin
de GroupJoin
(mientras que una join
sin una into
es 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) })
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) }