Ho questa linea che funziona finché non ho abilitato RelationalEventId.QueryClientEvaluationWarning.
Qui diciamo che quello che voglio fare è ordinare i risultati (clienti) in base alla loro ultima data dell'ordine.
.OrderByDescending(x=>x.orders.Max(y=>y.CreateDate))
Dopo aver configurato il contesto come segue mi sono reso conto che Max () non è stato convertito in TSql.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.ConfigureWarnings(warning =>
{
warning.Throw(RelationalEventId.QueryClientEvaluationWarning);
});
}
L'errore:
InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning: The LINQ expression 'Max()' could not be translated and will be evaluated locally.
Presumo che calcolare il massimo localmente sia contrario a prestazioni migliori. C'è un modo per calcolare il massimo su SQL Server?
Quando chiamate metodi aggregati (Media, Min, Max) in una query LINQ utilizzando un tipo non nullable, non ha altra scelta che valutarla localmente.
Per evitare ciò, lancia il valore Max su un valore nullable e verrà valutato nel database.
Supponendo che CreateDate sia di tipo DateTime, convertendolo in DateTime? (nullable) dovrebbe funzionare.
Ecco come dovrebbe apparire la tua query:
.OrderByDescending(x=>x.orders.Max(y=> (DateTime?)y.CreateDate))
Se hai abilitato la registrazione di core EF, visualizzerai il seguente avviso:
=> Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor
Possibile uso non intenzionale di un metodo di aggregazione potenzialmente generante (Min, Max, Media) in una sottoquery. Verrà utilizzata la valutazione del cliente e l'operatore effettuerà il lancio se non esiste alcun dato. La modifica del tipo di risultato della sottoquery su un tipo nullable consentirà la traduzione completa.
Fondamentalmente stanno cercando di preservare il comportamento di lancio dei summenzionati metodi di aggregazione in LINQ to Objects.
E la soluzione è nell'ultima frase. ad esempio se il tipo di CreateDate
è DateTime
, quindi
.OrderByDescending(x => x.orders.Max(y => (DateTime?)y.CreateDate))
sarà tradotto in SQL.