Perché forzare la materializzazione utilizzando ToList()
rende i miei ordini di query di grandezza più veloci quando, semmai, dovrebbe fare l'esatto opposto?Perché l'aggiunta di una ToList() non necessaria velocizza drasticamente questa query LINQ?
1) Chiamare First()
immediatamente
// "Context" is an Entity Framework DB-first model
var query = from x in Context.Users
where x.Username.ToLower().Equals(User.Identity.Name.ToLower())
select x;
var User = query.First();
// ** The above takes 30+ seconds to run **
2) Calling First()
dopo chiamando ToList()
:
var query = from x in Context.Users
where x.Username.ToLower().Equals(User.Identity.Name.ToLower())
select x;
var User = query.ToList().First(); // Added ToList() before First()
// ** Now it takes < 1 second to run! **
Update e risoluzione
Dopo avere ottenuto l'SQL generato, l'unica differenza è, come previsto, l'aggiunta di TOP (1)
nella prima query. Come dice Andyz Smith nella sua risposta di seguito, la causa principale è che l'ottimizzatore di SQL Server, in questo caso particolare, sceglie un piano di esecuzione peggiore quando viene aggiunto TOP (1)
. Quindi il problema non ha nulla a che fare con LINQ (che ha fatto la cosa giusta aggiungendo TOP (1)
) e tutto ciò che ha a che fare con le idiosincrasie di SQL Server.
Poiché il problema ha continuato ad essere indagato, la questione è stata svolta in un'altra domanda, quindi ho pensato che avrei dovuto ripulirlo e contrassegnarlo come risposta, dal momento che la domanda originale (perché LINQ sembrava fare qualcosa di molto strano) è stata effettivamente risposta. Grazie a tutti per l'aiuto su questo. – JoeCool
A meno che non ci sia un buon motivo per mantenere chiusa questa domanda dopo averla drasticamente pulita, riaprire. Grazie. – JoeCool
Se si sta solo per un singolo record, si dovrebbe usare .Single, usando. Per prima cosa si ha la possibilità che ci sia più di una riga corrispondente e non si possono ottenere i dati che ci si aspetta. – Chris