Esecuzione di queryQuery Execution

Dopo essere stata creata da un utente, una query LINQ viene convertita in un albero dei comandi.After a LINQ query is created by a user, it is converted to a command tree. Un albero dei comandi è una rappresentazione di una query compatibile con Entity Framework.A command tree is a representation of a query that is compatible with the Entity Framework. L'albero dei comandi viene quindi eseguito sull'origine dati.The command tree is then executed against the data source. In fase di runtime della query, tutte le espressioni di query, ovvero tutti i componenti della query, vengono valutate, incluse le espressioni usate nella materializzazione del risultato.At query execution time, all query expressions (that is, all components of the query) are evaluated, including those expressions that are used in result materialization.

Il momento di esecuzione delle espressioni di query può variare.At what point query expressions are executed can vary. Le query LINQ vengono sempre eseguite quando la variabile di query viene scorsa e non quando viene creata.LINQ queries are always executed when the query variable is iterated over, not when the query variable is created. Si tratta di esecuzione posticipata.This is called deferred execution. È inoltre possibile forzare l'esecuzione immediata di una query. Questa operazione è utile per memorizzare nella cache i risultati della queryYou can also force a query to execute immediately, which is useful for caching query results. e verrà descritta di seguito in questo argomento.This is described later in this topic.

Quando viene eseguita una query LINQ to Entities, è possibile che alcune espressioni nella query vengano eseguite nel server e che alcune parti vengano eseguite localmente nel client.When a LINQ to Entities query is executed, some expressions in the query might be executed on the server and some parts might be executed locally on the client. La valutazione sul lato client di un'espressione viene effettuata prima dell'esecuzione della query nel server.Client-side evaluation of an expression takes place before the query is executed on the server. Se un'espressione viene valutata nel client, il risultato della valutazione sostituisce l'espressione nella query e la query viene quindi eseguita nel server.If an expression is evaluated on the client, the result of that evaluation is substituted for the expression in the query, and the query is then executed on the server. Poiché le query vengono eseguite sull'origine dati, la configurazione dell'origine dati prevale sul comportamento specificato nel client.Because queries are executed on the data source, the data source configuration overrides the behavior specified in the client. La gestione dei valori Null e la precisione numerica dipendono ad esempio dalle impostazioni del server.For example, null value handling and numerical precision depend on the server settings. Tutte le eccezioni generate durante l'esecuzione della query nel server vengono passate direttamente al client.Any exceptions thrown during query execution on the server are passed directly up to the client.

Suggerimento

Per un utile riepilogo degli operatori di query in formato tabella, che consente di identificare rapidamente il comportamento di esecuzione di un operatore, vedere classificazione di operatori di Query Standard dalla modalità di esecuzione (c#).For a convenient summary of query operators in table format, which lets you quickly identify an operator's execution behavior, see Classification of Standard Query Operators by Manner of Execution (C#).

Esecuzione di query posticipataDeferred query execution

In una query che restituisce una sequenza di valori, la variabile di query stessa non contiene mai i risultati della query ma viene usata solo per l'archiviazione dei comandi della query.In a query that returns a sequence of values, the query variable itself never holds the query results and only stores the query commands. L'esecuzione della query viene posticipata finché non viene eseguita un'iterazione della variabile di query in un ciclo foreach o For Each.Execution of the query is deferred until the query variable is iterated over in a foreach or For Each loop. Questo è noto come esecuzione posticipata; ovvero, query viene eseguita qualche tempo dopo la query viene costruita.This is known as deferred execution; that is, query execution occurs some time after the query is constructed. È quindi possibile eseguire una query il numero di volte desiderato.This means that you can execute a query as frequently as you want to. Tale caratteristica è utile, ad esempio, quando si dispone di un database che viene aggiornato da altre applicazioni.This is useful when, for example, you have a database that is being updated by other applications. Nell'applicazione è possibile creare una query per recuperare le informazioni più recenti ed eseguire ripetutamente la query che restituisce ogni volta le informazioni aggiornate.In your application, you can create a query to retrieve the latest information and repeatedly execute the query, returning the updated information every time.

L'esecuzione posticipata consente di combinare più query o di estendere una query.Deferred execution enables multiple queries to be combined or a query to be extended. Una query estesa viene modificata in modo da includere nuove operazioni. Le modifiche verranno quindi riflesse nell'eventuale esecuzione.When a query is extended, it is modified to include the new operations, and the eventual execution will reflect the changes. Nell'esempio seguente la prima query restituisce tutti i prodotti.In the following example, the first query returns all the products. La seconda query estende la prima usando Where per restituire tutti i prodotti di taglia "L":The second query extends the first by using Where to return all the products of size "L":

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    IQueryable<Product> productsQuery =
        from p in context.Products
        select p;

    IQueryable<Product> largeProducts = productsQuery.Where(p => p.Size == "L");

    Console.WriteLine("Products of size 'L':");
    foreach (var product in largeProducts)
    {
        Console.WriteLine(product.Name);
    }
}
Using context As New AdventureWorksEntities()
    Dim productsQuery = _
        From p In context.Products _
        Select p

    Dim largeProducts = _
        productsQuery.Where(Function(p) p.Size = "L")

    Console.WriteLine("Products of size 'L':")
    For Each product In largeProducts
        Console.WriteLine(product.Name)
    Next
End Using

Dopo aver eseguito una query, per tutte le query successive vengono usati gli operatori LINQ in memoria.After a query has been executed all successive queries will use the in-memory LINQ operators. Se si scorre una variabile di query usando un'istruzione foreach o For Each o chiamando uno degli operatori di conversione LINQ, la query viene eseguita immediatamente.Iterating over the query variable by using a foreach or For Each statement or by calling one of the LINQ conversion operators will cause immediate execution. Gli operatori di conversione includono ToList, ToArray, ToLookup e ToDictionary.These conversion operators include the following: ToList, ToArray, ToLookup, and ToDictionary.

Esecuzione di query immediataImmediate Query Execution

A differenza dell'esecuzione posticipata delle query che restituiscono una sequenza di valori, le query che restituiscono un valore singleton vengono eseguite immediatamente.In contrast to the deferred execution of queries that produce a sequence of values, queries that return a singleton value are executed immediately. Alcuni esempi di query singleton sono Average, Count, First e Max.Some examples of singleton queries are Average, Count, First, and Max. Tali query vengono eseguite immediatamente perché la query deve restituire una sequenza per calcolare il risultato singleton.These execute immediately because the query must produce a sequence to calculate the singleton result. È anche possibile forzare l'esecuzione immediata.You can also force immediate execution. Questa operazione è utile quando si desidera memorizzare nella cache i risultati di una query.This is useful when you want to cache the results of a query. Per forzare l'esecuzione immediata di una query che non restituisce un valore singleton, è possibile chiamare il metodo ToList, ToDictionary o ToArray su una query o su una variabile di query.To force immediate execution of a query that does not produce a singleton value, you can call the ToList method, the ToDictionary method, or the ToArray method on a query or query variable. Nell'esempio seguente viene usato il metodo ToArray per restituire immediatamente una matrice da una sequenza.The following example uses the ToArray method to immediately evaluate a sequence into an array.

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    ObjectSet<Product> products = context.Products;

    Product[] prodArray = (
        from product in products
        orderby product.ListPrice descending
        select product).ToArray();

    Console.WriteLine("Every price from highest to lowest:");
    foreach (Product product in prodArray)
    {
        Console.WriteLine(product.ListPrice);
    }
}
Using context As New AdventureWorksEntities
    Dim products As ObjectSet(Of Product) = context.Products

    Dim prodArray As Product() = ( _
        From product In products _
        Order By product.ListPrice Descending _
        Select product).ToArray()

    Console.WriteLine("The list price from highest to lowest:")
    For Each prod As Product In prodArray
        Console.WriteLine(prod.ListPrice)
    Next
End Using

È anche possibile forzare l'esecuzione inserendo il ciclo foreach o For Each immediatamente dopo l'espressione di query, mentre chiamando ToList o ToArray si memorizzano nella cache tutti i dati in un singolo oggetto Collection.You could also force execution by putting the foreach or For Each loop immediately after the query expression, but by calling ToList or ToArray you cache all the data in a single collection object.

Esecuzione nell'archivioStore Execution

Poiché in genere le espressioni in LINQ to Entities vengono valutate nel server, non è previsto che il comportamento dell'espressione sia conforme alla semantica CLR (Common Language Runtime), ma piuttosto a quella dell'origine dati.In general, expressions in LINQ to Entities are evaluated on the server, and the behavior of the expression should not be expected to follow common language runtime (CLR) semantics, but those of the data source. Vi sono tuttavia eccezioni, ad esempio quando l'espressione viene eseguita nel client.There are exceptions to this, however, such as when the expression is executed on the client. Questo può provocare risultati imprevisti, ad esempio quando il server e il client si trovano in fusi orari diversi.This could cause unexpected results, for example when the server and client are in different time zones.

Alcune espressioni nella query possono venire eseguite nel client.Some expressions in the query might be executed on the client. In generale, è previsto che la maggior parte dell'esecuzione della query avvenga nel server.In general, most query execution is expected to occur on the server. Oltre ai metodi eseguiti su elementi della query mappati all'origine dati, vi sono spesso espressioni nella query che possono essere eseguite localmente.Aside from methods executed against query elements mapped to the data source, there are often expressions in the query that can be executed locally. L'esecuzione locale di un'espressione di query produce un valore che può essere usato nell'esecuzione della query o nella costruzione del risultato.Local execution of a query expression yields a value that can be used in the query execution or result construction.

Determinate operazioni vengono eseguite sempre nel client, ad esempio l'associazione di valori, le sottoespressioni, le sottoquery e la materializzazione di oggetti nei risultati della query.Certain operations are always executed on the client, such as binding of values, sub expressions, sub queries from closures, and materialization of objects into query results. Di conseguenza questi elementi, ad esempio i valori dei parametri, non possono essere aggiornati durante l'esecuzione.The net effect of this is that these elements (for example, parameter values) cannot be updated during the execution. I tipi anonimi possono essere costruiti inline nell'origine dati, ma questo comportamento non deve essere presupposto.Anonymous types can be constructed inline on the data source, but should not be assumed to do so. Anche i raggruppamenti inline possono essere costruiti nell'origine dati, ma questo comportamento non deve essere presupposto in ogni istanza.Inline groupings can be constructed in the data source, as well, but this should not be assumed in every instance. In generale, è consigliabile non fare presupposizioni relativamente agli elementi che verranno costruiti nel server.In general, it is best not to make any assumptions about what is constructed on the server.

Contenuto della sezione vengono descritti scenari in cui il codice viene eseguito localmente nel client.This section describes the scenarios in which code is executed locally on the client. Per ulteriori informazioni sui tipi di espressioni vengono eseguiti in locale, vedere espressioni nelle query LINQ to Entities.For more information about which types of expressions are executed locally, see Expressions in LINQ to Entities Queries.

Valori letterali e parametriLiterals and Parameters

Le variabili locali, ad esempio la variabile orderID nell'esempio seguente, vengono valutate nel client.Local variables, such as the orderID variable in the following example, are evaluated on the client.

int orderID = 51987;

IQueryable<SalesOrderHeader> salesInfo =
    from s in context.SalesOrderHeaders
    where s.SalesOrderID == orderID
    select s;
Dim orderID As Integer = 51987

Dim salesInfo = _
    From s In context.SalesOrderHeaders _
    Where s.SalesOrderID = orderID _
    Select s

Anche i parametri dei metodi vengono valutati nel client.Method parameters are also evaluated on the client. Un esempio è costituito dal parametro orderID passato al metodo MethodParameterExample, come illustrato di seguito.The orderID parameter passed into the MethodParameterExample method, below, is an example.

public static void MethodParameterExample(int orderID)
{
    using (AdventureWorksEntities context = new AdventureWorksEntities())
    {
        
        IQueryable<SalesOrderHeader> salesInfo =
            from s in context.SalesOrderHeaders
            where s.SalesOrderID == orderID
            select s;                

        foreach (SalesOrderHeader sale in salesInfo)
        {
            Console.WriteLine("OrderID: {0}, Total due: {1}", sale.SalesOrderID, sale.TotalDue);
        }
    }
}
Function MethodParameterExample(ByVal orderID As Integer)
    Using context As New AdventureWorksEntities()

        Dim salesInfo = _
            From s In context.SalesOrderHeaders _
            Where s.SalesOrderID = orderID _
            Select s

        Console.WriteLine("Sales order info:")
        For Each sale As SalesOrderHeader In salesInfo
            Console.WriteLine("OrderID: {0}, Total due: {1}", sale.SalesOrderID, sale.TotalDue)
        Next
    End Using

End Function

Esecuzione del cast di valori letterali nel clientCasting Literals on the Client

Il cast da un valore null a un tipo CLR viene eseguito nel client:Casting from null to a CLR type is executed on the client:

IQueryable<Contact> query =
    from c in context.Contacts
    where c.EmailAddress == (string)null
    select c;
Dim query = _
    From c In context.Contacts _
    Where c.EmailAddress = CType(Nothing, String) _
    Select c

Il cast a un tipo, ad esempio un oggetto Decimal che ammette i valori Null, viene eseguito nel client:Casting to a type, such as a nullable Decimal, is executed on the client:

var weight = (decimal?)23.77;
IQueryable<Product> query =
    from product in context.Products
    where product.Weight == weight
    select product;
Dim weight = CType(23.77, Decimal?)
Dim query = _
    From product In context.Products _
        Where product.Weight = weight _
        Select product

Costruttori per i valori letteraliConstructors for Literals

I nuovi tipi CLR di cui è possibile eseguire il mapping al modello concettuale vengono eseguiti nel client:New CLR types that can be mapped to conceptual model types are executed on the client:

var weight = new decimal(23.77);
IQueryable<Product> query =
    from product in context.Products
    where product.Weight == weight
    select product;
Dim weight = New Decimal(23.77)
Dim query = _
    From product In context.Products _
    Where product.Weight = weight _
    Select product

Anche le nuove matrici vengono eseguite nel client.New arrays are also executed on the client.

Eccezioni nell'archivioStore Exceptions

Qualsiasi errore che si verifica nell'archivio durante l'esecuzione della query viene passato al client e non viene mappato o gestito.Any store errors that are encountered during query execution are passed up to the client, and are not mapped or handled.

Configurazione dell'archivioStore Configuration

Quando la query viene eseguita nell'archivio, la configurazione dell'archivio sostituisce tutti i comportamenti client e la semantica dell'archivio viene espressa per tutte le operazioni e le espressioni.When the query executes on the store, the store configuration overrides all client behaviors, and store semantics are expressed for all operations and expressions. Ciò può determinare una differenza nel comportamento tra l'esecuzione nell'archivio e quella conforme a CLR per quanto riguarda aspetti come il confronto di valori Null, l'ordinamento di GUID, la precisione e l'accuratezza di operazioni che includono tipi di dati non precisi, ad esempio tipi a virgola mobile o DateTime, e le operazioni di stringa.This can result in a difference in behavior between CLR and store execution in areas such as null comparisons, GUID ordering, precision and accuracy of operations involving non-precise data types (such as floating point types or DateTime), and string operations. È importante tenere presente questo aspetto quando si esaminano i risultati della query.It is important to keep this in mind when examining query results.

Di seguito vengono illustrate alcune differenze di comportamento tra CLR e SQL Server:For example, the following are some differences in behavior between the CLR and SQL Server:

  • In SQL Server i GUID vengono ordinati in modo diverso rispetto a CLR.SQL Server orders GUIDs differently than the CLR.

  • Possono esserci anche differenze nella precisione del risultato in caso di utilizzo del tipo Decimal in SQL Server.There can also be differences in result precision when dealing with the Decimal type on SQL Server. Queste differenze sono dovute ai requisiti fissi di precisione del tipo Decimal in SQL Server.This is due to the fixed precision requirements of the SQL Server decimal type. La media dei valori Decimal 0,0, 0,0 e 1,0 è ad esempio 0,3333333333333333333333333333 nella memoria del client, ma 0,333333 nell'archivio, in base alla precisione predefinita per il tipo Decimal di SQL Server.For example, the average of Decimal values 0.0, 0.0, and 1.0 is 0.3333333333333333333333333333 in memory on the client, but 0.333333 in the store (based on the default precision for SQL Server’s decimal type).

  • Anche alcune operazioni di confronto di stringhe vengono gestite in SQL Server in modo diverso rispetto a quanto avviene in CLR.Some string comparison operations are also handled differently in SQL Server than in the CLR. Il comportamento del confronto di stringhe dipende dalle impostazioni delle regole di confronto nel server.String comparison behavior depends on the collation settings on the server.

  • Le chiamate alle funzioni o ai metodi, quando incluse in una query LINQ to Entities, vengono mappate a funzioni canoniche in Entity Framework, che vengono convertite quindi in Transact-SQL ed eseguite nel database di SQL Server.Function or method calls, when included in a LINQ to Entities query, are mapped to canonical functions in the Entity Framework, which are then translated to Transact-SQL and executed on the SQL Server database. In alcuni casi il comportamento delle funzioni mappate può differire dall'implementazione nelle librerie di classi di base.There are cases when the behavior these mapped functions exhibit might differ from the implementation in the base class libraries. La chiamata ai metodi Contains, StartsWith e EndsWith con una stringa vuota come parametro restituisce ad esempio true quando eseguita in CLR, mentre restituisce false in caso di esecuzione in SQL Server.For example, calling the Contains, StartsWith, and EndsWith methods with an empty string as a parameter will return true when executed in the CLR, but will return false when executed in SQL Server. Anche il metodo EndsWith può restituire risultati diversi, in quanto due stringhe che differiscono solo per lo spazio vuoto finale vengono considerate uguali in SQL Server ma non in CLR.The EndsWith method can also return different results because SQL Server considers two strings to be equal if they only differ in trailing white space, whereas the CLR considers them to be not equal. Questo comportamento è illustrato nell'esempio seguente:This is illustrated by the following example:

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    IQueryable<string> query = from p in context.Products
                               where p.Name == "Reflector"
                               select p.Name;

    IEnumerable<bool> q = query.Select(c => c.EndsWith("Reflector "));

    Console.WriteLine("LINQ to Entities returns: " + q.First());
    Console.WriteLine("CLR returns: " + "Reflector".EndsWith("Reflector "));

}
Using context As New AdventureWorksEntities()

    Dim query = _
        From p In context.Products _
        Where p.Name = "Reflector" _
        Select p.Name

    Dim q = _
        query.Select(Function(c) c.EndsWith("Reflector "))

    Console.WriteLine("LINQ to Entities returns: " & q.First())
    Console.WriteLine("CLR returns: " & "Reflector".EndsWith("Reflector "))
End Using