Sto vedendo alcuni perf perfetti relativi a una query molto semplice usando Entity Framework Code-First con .NET framework versione 4. La query LINQ2Entities ha il seguente aspetto:
context.MyTables.Where(m => m.SomeStringProp == stringVar);
Questo richiede oltre 3000 millisecondi da eseguire. L’SQL generato sembra molto semplice:
SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp], ... FROM [MyTable] as [Extent1] WHERE [Extent1].[SomeStringProp] = '1234567890'
Questa query viene eseguita quasi istantaneamente quando viene eseguita in Management Studio. Quando cambio il codice C # per utilizzare la funzione SqlQuery, viene eseguito in 5-10 millisecondi:
context.MyTables.SqlQuery("SELECT [Extent1].[ID] ... WHERE [Extent1].[SomeStringProp] = @param", stringVar);
Quindi, esattamente lo stesso SQL, le entity framework risultanti vengono tracciate in base al cambiamento in entrambi i casi, ma la differenza è perfetta tra i due. Cosa dà?
Trovato. Risulta che si tratta di un problema di tipi di dati SQL. La colonna SomeStringProp
nel database era un varchar, ma EF presuppone che i tipi di stringhe .NET siano nvarchars. Il processo di traduzione risultante durante la query per il DB per eseguire il confronto è ciò che richiede molto tempo. Penso che EF Prof mi stia portando un po ‘fuori strada qui, una rappresentazione più accurata della query da eseguire sarebbe la seguente:
SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp], ... FROM [MyTable] as [Extent1] WHERE [Extent1].[SomeStringProp] = N'1234567890'
Quindi la correzione risultante è di annotare il modello code-first, indicando il tipo di dati SQL corretto:
public class MyTable { ... [Column(TypeName="varchar")] public string SomeStringProp { get; set; } ... }
La ragione di rallentare le mie query fatte in EF è stata la comparazione di scalari non annullabili con scalari nullable:
long? userId = 10; // nullable scalar db.Table().Where(x => x.User.Id == userId).ToList() // or userId.Value ^^^^^^^^^ ^^^^^^ Type: long Type: long?
Quella domanda ha richiesto 35 secondi. Ma un piccolo refactoring del genere:
long? userId = 10; long userIdValue = userId.Value; // I've done that only for the presentation pursposes db.Table().Where(x => x.User.Id == userIdValue).ToList() ^^^^^^^^^ ^^^^^^^^^^^ Type: long Type: long
dà risultati incredibili. Ci sono voluti solo 50ms per completare. È ansible che si tratti di un bug in EF.
Se stai utilizzando la mapping fluente, puoi utilizzare IsUnicode(false)
come parte della configurazione per ottenere lo stesso effetto:
http://msdn.microsoft.com/en-us/data/jj591617.aspx#1.9
http://msdn.microsoft.com/en-us/library/gg696416%28v=vs.103%29.aspx
Ho avuto lo stesso problema (la query è veloce quando eseguita dal gestore SQL) ma quando viene eseguita da EF il timeout scade.
Risulta che l’ quadro (che era stata creata dalla vista) aveva chiavi di quadro errate. Quindi l’ quadro aveva righe duplicate con le stesse chiavi, e immagino che doveva fare il raggruppamento sullo sfondo.
Ho anche trovato questo con una query ef complessa. Una soluzione per me che ha ridotto una query ef di 6 secondi alla query sql sub second che ha generato è stata quella di distriggersre il caricamento lazy.
Per trovare questa impostazione (ef 6), accedere al file .edmx e cercare Proprietà -> Generazione codice -> Caricamento pigro abilitato. Impostato su falso.
Un enorme miglioramento delle prestazioni per me.
Puoi usare i seguenti trucchi per fissare le tue domande –
ctx.Configuration.ProxyCreationEnabled
su false
right prima di ottenere il contesto. .Select(c => new {c.someproperty})
solo i dati richiesti e non l’intero gruppo. Fammi sapere se ti è stato d’aiuto.
Ho avuto anche questo problema. Si scopre che il colpevole nel mio caso era lo sniffing dei parametri SQL-Server.
Il primo indizio che il mio problema era in effetti dovuto allo sniffing dei parametri era che l’esecuzione della query con “set arithabort off” o “set arithabort on” produceva tempi di esecuzione drasticamente differenti in Management Studio. Ciò è dovuto al fatto che ADO.NET utilizza per impostazione predefinita “set arithabort off” e i valori predefiniti di Management Studio su “set arithabort on”. La cache del piano di query mantiene piani diversi a seconda di questo parametro.
Ho disabilitato il caching del piano di query per la query, con la soluzione che puoi trovare qui .