Domanda

Dato la seguente query LINQ a SQL:

var test = from i in Imports
           where i.IsActive
           select i;
.

L'istruzione SQL interpretata è:

SELECT [t0].[id] AS [Id] .... FROM [Imports] AS [t0] WHERE [t0].[isActive] = 1
.

Dì che volevo eseguire qualche azione nella selezione che non può essere convertita in SQL.È la mia comprensione che il modo convenzionale per realizzare questo è quello di fare AsEnumerable() convertendolo così in un oggetto praticabile.

Dato questo codice aggiornato:

var test = from i in Imports.AsEnumerable()
           where i.IsActive
           select new 
           { 
               // Make some method call 
           };
.

e aggiornato SQL:

SELECT [t0].[id] AS [Id] ... FROM [Imports] AS [t0] 
.

Avvia la mancanza di una clausola WHERE nell'istruzione SQL eseguita.

Significa che l'intera tabella "importazioni" è memorizzata nella memorizzazione nella memoria? Questa prestazione lenta se il tavolo contenesse una grande quantità di record?

Aiutami a capire cosa sta effettivamente accadere dietro le quinte qui.

È stato utile?

Soluzione

Il motivo per Asenumerable è

.

Asenumerable (TSOURCE) (IIMUMACERARE (TSOURCE)) può essere usato per scegliere tra query implementazioni quando una sequenza implementa ienumerable (t) ma ha anche Un insieme diverso di query pubblica Metodi disponibili

Quindi quando si stava chiamando il metodo Where prima, stavi chiamando un metodo Where diverso da IEnumerable.Where. Quell'istruzione Where era per LINQ da convertire in SQL, il nuovo Where è il IEnumerable che assume un IEnumerable, enumeralo e produce gli elementi corrispondenti. Il che spiega perché vedi il diverso sql che viene generato. La tabella verrà presa per intero dal database prima che l'estensione Where verrà applicata nella seconda versione del codice. Questo potrebbe creare un collo di bottiglia serio, perché l'intera tabella deve essere in memoria, o peggiore l'intera tabella dovrebbe viaggiare tra i server. Consenti SQL Server di eseguire il Where e fare ciò che fa meglio.

Altri suggerimenti

Nel punto in cui l'enumerazione viene elencata attraverso, il database verrà quindi interrogato e l'intero Ristorante ha recuperato.

Una soluzione a part-and-part può essere la strada.Considera

var res = (
    from result in SomeSource
    where DatabaseConvertableCriterion(result)
    && NonDatabaseConvertableCriterion(result)
    select new {result.A, result.B}
);
.

Diciamo anche che non hatabaseconvertablecreditore richiede il campo C dal risultato.Poiché NondatabaseConvertableCriterion fa ciò che suggerisce il suo nome, questo deve essere eseguito come un'enumerazione.Tuttavia, considera:

var partWay =
(
    from result in SomeSource
    where DatabaseConvertableCriterion(result)
    select new {result.A, result.B, result.C}
);
var res =
(
    from result in partWay.AsEnumerable()
    where NonDatabaseConvertableCriterion select new {result.A, result.B}
);
.

In questo caso, quando la risoluzione è enumerata, interrogata o altrimenti utilizzata, il più lavoro possibile sarà passato al database, che ritornerà abbastanza per continuare il lavoro.Supponendo che sia davvero davvero impossibile riscrivere in modo che tutto il lavoro possa essere inviato al database, questo potrebbe essere un compromesso adatto.

Ci sono tre implementazioni di AsEnumerable.

DataTableExtensions.AsEnumerable

Estende un DataTable per dargli un'interfaccia IEnumerable in modo da poter utilizzare LINQ contro il DataTable.

Enumerable.AsEnumerable<TSource> e ParallelEnumerable.AsEnumerable<TSource> < / Strong>

.

Il metodo AsEnumerable<TSource>(IEnumerable<TSource>) non ha alcun effetto diverso da quello di modificare il tipo di sorgente di compilazione da un tipo implementa IEnumerable<T> a IEnumerable<T> stesso.

AsEnumerable<TSource>(IEnumerable<TSource>) può essere utilizzato per scegliere Tra le implementazioni della query quando una sequenza implementa IEnumerable<T> ma ha anche un insieme diverso di metodi di query pubblica a disposizione. Ad esempio, dato un generatore di classe generico Table che implementa IEnumerable<T> e ha i propri metodi come Where, Select e SelectMany, una chiamata a Where invocherebbe il metodo del Where pubblico Table. Un tipo Table che rappresenta una tabella di database potrebbe avere un Metodo Where che prende l'argomento predicato come un albero di espressione e converte l'albero su SQL per l'esecuzione remota. Se l'esecuzione remota non è desiderato, ad esempio perché il predicato invoca un locale Metodo, il metodo AsEnumerable<TSource> può essere utilizzato per nascondere il Metodi personalizzati e invece rendono gli operatori di query standard Disponibile.

in altre parole.

Se ho un

IQueryable<X> sequence = ...;
.

Da un LinqProvider, come il framework di entità e lo faccio,

sequence.Where(x => SomeUnusualPredicate(x));
.

Quella query sarà composta e eseguita sul server. Questo fallirà in fase di esecuzione perché l'entityframework non sa come convertire SomeUnusualPredicate in SQL.

Se voglio che eseguire la dichiarazione con LINQ agli oggetti invece, lo faccio,

sequence.AsEnumerable().Where(x => SomeUnusualPredicate(x));
.

Ora il server restituirà tutti i dati e verranno utilizzati Enumerable.Where da LINQ a Oggetti al posto dell'implementazione del provider di query.

Non importa che il framework di entità non sappia interpretare SomeUnusualPredicate, la mia funzione verrà utilizzata direttamente. (Tuttavia, questo può essere un approccio inefficiente poiché tutte le righe verranno restituite dal server.)

Credo che l'Asenumeracraffracracraffracracraffracracraffracrable debba comunicare al compilatore che metodi di estensione da utilizzare (in questo caso quelli definiti per Ienumerable invece di quelli per iqueryable). L'esecuzione della query è ancora rinviata finché non si chiamano torre o enumerano su di esso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top