Sto lavorando in Entity Framework Core 1.1.0 (e l'aggiornamento non è un'opzione a questo punto, a causa di rotture delle modifiche nelle versioni successive). La mia domanda è del seguente modulo:
var q = db.MyTable
.GroupBy(t => new { t.Field1 })
.Select(g => new
{
g.Key.Field1,
MaxField2 = g.Max(x => x.Field2)
})
.ToList();
Nel codice di prova funziona bene e restituisce i dati previsti. Ma quando viene implementato in un ambiente reale, con dati reali, scade. Perché? Bene, ho messo uno sniffer sul server SQL, e qui c'è l'SQL reale:
SELECT [t].[Field1], [t].[Field2], [t].[Field3], [t].[Field4], [t].[Field5]
FROM [dbo].[MyTable] AS [t]
ORDER BY [t].[Field1]
Oh. Beh, questo lo spiegherebbe. EF sta solo compilando la query fino a .GroupBy()
in SQL, tentando così di caricare l' intero contenuto della tabella (circa 17 milioni di record in questo momento di scrittura) in memoria, e il resto del raggruppamento e dell'ordine è supposto da fare in memoria.
Qualche suggerimento su come rielaborare questa query in modo che il sollevamento pesante avvenga in SQL?
Come sottolinea @xanatos, questo non è supportato in EF Core 1.1.0 (e nemmeno 2.0.0). Esiste, tuttavia, una soluzione alternativa, utilizzando SQL letterale:
var q = db.MyTable
.FromSql("select t.* from " +
" (select distinct Field1 from MyTable) t0 " +
"cross apply " +
" (select top 1 t.* from MyTable t " +
" where t.Field1 = t0.Field1 " +
" order by t.Field2 desc) t")
.Select(t => new
{
t.Field1,
MaxField2 = t.Field2
})
.ToList();
Non è la soluzione che speravo, ma ha un fascino.
Non supportato in EF Core 1.1.0: https://github.com/aspnet/EntityFramework/issues/2341
Gli operatori GroupBy () di LINQ possono talvolta essere tradotti in clausole GROUP BY di SQL, in particolare quando le funzioni di aggregazione vengono applicate nella proiezione.
Purtroppo non sarà supportato nemmeno in EF Core 2.0.0.