El objetivo es obtener el primer DateTime y el último DateTime de una colección en una entidad (clave externa). Mi entidad es una organización y mi colección son facturas. Estoy agrupando resultados ya que las organizaciones desafortunadamente no son únicas. Estoy tratando con datos duplicados y no puedo asumir que mis organizaciones son únicas, por lo que estoy agrupando por un campo de Número en mi Entidad.
Estoy usando .NET Core 2.1.2 con Entity Framework.
Estoy tratando de obtener la siguiente consulta generada desde LINQ:
SELECT MIN([organization].[Id]) AS Id, MIN([organization].[Name]) AS Name,
MIN([organization].[Number]) AS Number, MIN([invoice].[Date])
AS First, MAX([invoice].[Date]) AS Last
FROM [organization]
INNER JOIN [invoice] ON [invoice].[OrganizationId] = [organization].[Id]
GROUP BY [organization].[Number], [organization].[Name]
ORDER BY [organization].[Name]
Sin embargo, no tengo idea de cómo escribir la consulta LINQ para obtener este resultado.
Llegué hasta
await _context
.Organization
.Where(z => z.Invoices.Any())
.GroupBy(organization => new
{
organization.Number,
organization.Name
})
.Select(grouping => new
{
Id = grouping.Min(organization => organization.Id),
Name = grouping.Min(organization => organization.Name),
Number= grouping.Min(organization => organization.Number),
//First = ?,
//Last = ?
})
.OrderBy(z => z.Name)
.ToListAsync();
No tengo ni idea de cómo escribir la consulta LINQ de tal manera que genere lo anterior.
Todavía tengo un par de preguntas:
¿Alguien sabe cómo terminar de escribir la declaración LINQ? Como tengo que obtener la primera y la última fecha de la Colección de facturas en mi entidad de organización:
organization.Invoices.Min(invoice => invoice.Date)
organization.Invoices.Max(invoice => invoice.Date)
Aquí está el truco.
Para hacer inner join
utilizando la propiedad de navegación de colección, use SelectMany
y proyecte todas las propiedades primitivas que necesite más adelante (esto es importante para el actual traductor de consultas de EF Core). Luego realice el GroupBy
y proyecte las propiedades / agregados clave. Finalmente hacer el pedido.
Asi que
var query = _context
.Organization
.SelectMany(organization => organization.Invoices, (organization, invoice) => new
{
organization.Id,
organization.Number,
organization.Name,
invoice.Date
})
.GroupBy(e => new
{
e.Number,
e.Name
})
.Select(g => new
{
Id = g.Min(e => e.Id),
Name = g.Key.Name,
Number = g.Key.Number,
First = g.Min(e => e.Date),
Last = g.Max(e => e.Date),
})
.OrderBy(e => e.Name);
se traduce a
SELECT MIN([organization].[Id]) AS [Id], [organization].[Name], [organization].[Number],
MIN([organization.Invoice].[Date]) AS [First], MAX([organization.Invoice].[Date]) AS [Last]
FROM [Organization] AS [organization]
INNER JOIN [Invoice] AS [organization.Invoice] ON [organization].[Id] = [organization.Invoice].[OrganizationId]
GROUP BY [organization].[Number], [organization].[Name]
ORDER BY [organization].[Name]