Condividi tramite


Determinazione della struttura dei risultati di query (Entity Framework)

Quando si esegue una query, vengono restituiti solo gli oggetti richiesti in maniera specifica nella query. Quando, ad esempio, da una query sul modello Sales di AdventureWorks vengono restituiti oggetti Customer, per impostazione predefinita gli oggetti SalesOrderHeader correlati non vengono restituiti, anche se vi è una relazione tra Customer e SalesOrderHeader. Questo comportamento garantisce che nell'applicazione possa sempre essere previsto l'ambito dei dati restituiti da una query di oggetto. Per impostazione predefinita, gli oggetti relazione che rappresentano le associazioni tra tipi di entità vengono sempre restituiti. Quando vengono generati oggetti in base allo schema concettuale di EDM, vengono generate proprietà di navigazione per gli oggetti entità in entrambe le entità finali di un'associazione. Queste proprietà di navigazione restituiscono un oggetto EntityReference sul lato "uno" di una relazione uno-a-uno o molti-a-uno o un oggetto EntityCollection sul lato "molti" di una relazione uno-a-molti o molti-a-molti. Per ulteriori informazioni, vedere Relazioni in Entity Data Model.

È possibile creare una query Entity SQL o LINQ to Entities per la navigazione esplicita di queste relazioni tramite le proprietà di navigazione. Per ulteriori informazioni, vedere Procedura: spostarsi nelle relazioni utilizzando le proprietà di navigazione (Entity Framework). Per determinare la struttura dei risultati di query, non è tuttavia necessario eseguire la navigazione esplicita delle relazioni nella query. Per estendere i risultati di una query in modo che vengano caricati anche gli oggetti a cui si fa riferimento sono disponibili altri due metodi. È possibile specificare i percorsi della query oppure è possibile caricare in modo esplicito gli oggetti correlati utilizzando le proprietà di navigazione. Per controllare ulteriormente i risultati, è possibile definire un percorso della query e quindi caricare in modo esplicito solo gli oggetti correlati selezionati.

Nella scelta dell'opzione da utilizzare, considerare il compromesso tra il numero di richieste nel database e la quantità di dati restituiti in una singola query. I percorsi della query definiscono il grafico degli oggetti restituiti da una query. Quando si definisce un percorso della query, è necessaria una singola richiesta nel database per restituire tutti gli oggetti definiti dal percorso in un unico set di risultati. Per caricare in modo esplicito gli oggetti sono necessari più round trip al database e potrebbe essere necessaria la funzionalità MARS (Multiple Active Result Set), ma la quantità di dati restituiti è limitata esclusivamente agli oggetti caricati.

Definizione di un percorso della query per determinare la struttura dei risultati di query

Per specificare il percorso della query, passare una rappresentazione di stringa dell'oggetto grafico al metodo Include su ObjectQuery. Questo percorso specifica quali oggetti correlati restituire quando viene eseguita una query di oggetto. Un percorso della query definito in una query per gli oggetti Contact garantisce che vengano restituiti tutti gli oggetti SalesOrderHeader e SalesOrderDetail correlati. Questo comportamento è illustrato nelle query seguenti in cui vengono utilizzati metodi del generatore di query, LINQ to Entities e Entity SQL.

  • LINQ to Entities
``` vb
' Define a LINQ query with a path that returns 
' orders and items for a contact.
Dim contacts = (From contact In context.Contact _
    .Include("SalesOrderHeader.SalesOrderDetail") _
    Select contact).FirstOrDefault()
```

``` csharp
// Define a LINQ query with a path that returns 
// orders and items for a contact.
var contacts = (from contact in context.Contact
              .Include("SalesOrderHeader.SalesOrderDetail")
              select contact).FirstOrDefault();
```
  • Entity SQL
``` vb
' Define an object query with a path that returns 
' orders and items for a specific contact.              
Dim queryString As String = _
    "SELECT VALUE TOP(1) Contact FROM " + _
    "AdventureWorksEntities.Contact AS Contact"

' Define the object query with the query string.
Dim contactQuery As New ObjectQuery(Of Contact)(queryString, _
    context, MergeOption.NoTracking)

Dim contact As Contact = _
contactQuery.Include("SalesOrderHeader.SalesOrderDetail") _
    .FirstOrDefault()
```

``` csharp
// Define an object query with a path that returns 
// orders and items for a specific contact.              
string queryString =
    @"SELECT VALUE TOP(1) Contact FROM " + 
    "AdventureWorksEntities.Contact AS Contact";

// Define the object query with the query string.
ObjectQuery<Contact> contactQuery = new ObjectQuery<Contact>(queryString, 
    context, MergeOption.NoTracking);

Contact contact =
    contactQuery.Include("SalesOrderHeader.SalesOrderDetail")
    .FirstOrDefault();
```
  • Metodi del generatore di query

    ' Create an object query with a path that returns orders and items for a contact.
    Dim contact As Contact = _
        context.Contact.Include("SalesOrderHeader.SalesOrderDetail") _
        .FirstOrDefault()
    
    // Define an object query with a path that returns 
    // orders and items for a specific contact.
    Contact contact =
        context.Contact.Include("SalesOrderHeader.SalesOrderDetail")
        .FirstOrDefault();
    

Le considerazioni seguenti riguardano la definizione di percorsi della query:

  • I percorsi della query possono essere utilizzati con i metodi del generatore di query e con le query LINQ.

  • Quando si chiama Include, il percorso della query è valido solo nell'istanza restituita di ObjectQuery. Le altre istanze di ObjectQuery e il contesto dell'oggetto stesso non sono interessati.

  • Poiché Include restituisce l'oggetto query, è possibile chiamare questo metodo più volte su un oggetto ObjectQuery per includere oggetti di più relazioni, come nell'esempio seguente:

    ' Create a SalesOrderHeader query with two query paths, 
    ' one that returns order items and a second that returns the 
    ' billing and shipping addresses for each order.
    Dim query As ObjectQuery(Of SalesOrderHeader) = _
        context.SalesOrderHeader.Include("SalesOrderDetail").Include("Address")
    
    // Create a SalesOrderHeader query with two query paths, 
    // one that returns order items and a second that returns the 
    // billing and shipping addresses for each order.
    ObjectQuery<SalesOrderHeader> query =
        context.SalesOrderHeader.Include("SalesOrderDetail").Include("Address");
    
  • L'utilizzo di percorsi della query può comportare l'esecuzione di comandi complessi nell'origine dati, derivanti da query di oggetto apparentemente semplici. Questo si verifica in quanto per restituire oggetti correlati in una singola query sono necessari uno o più join. Questa complessità è maggiore nelle query su un modello EDM complesso, ad esempio un'entità con ereditarietà o un percorso che include relazioni molti-a-molti. Utilizzare il metodo ToTraceString per vedere il comando che verrà generato da ObjectQuery. Per ulteriori informazioni, vedere Query di oggetto (Entity Framework). Quando un percorso della query include troppi oggetti correlati o gli oggetti contengono troppi dati delle righe, la query potrebbe non venire completata dall'origine dati. Questo si verifica se la query richiede un'archiviazione temporanea intermedia superiore alle possibilità dell'origine dati. In questo caso, è possibile ridurre la complessità della query sull'origine dati caricando in modo esplicito gli oggetti correlati.

Per ulteriori informazioni, vedere Procedura: utilizzare percorsi di query per influenzare i risultati (Entity Framework).

Caricamento esplicito di oggetti correlati

Per caricare in modo esplicito gli oggetti correlati, è necessario chiamare il metodo Load sull'entità finale correlata restituita dalla proprietà di navigazione. Per una relazione uno-a-molti, chiamare il metodo Load su EntityCollection, mentre per una relazione uno-a-uno, chiamare Load su EntityReference. In questo modo, i dati degli oggetti correlati verranno caricati nel contesto dell'oggetto. Quando una query restituisce un insieme di oggetti, è possibile enumerare l'insieme e chiamare il metodo Load per caricare gli oggetti correlati per ogni oggetto dell'insieme, ad esempio ogni oggetto SalesOrderDetail appartenente a un oggetto SalesOrderHeader. Nell'esempio seguente gli oggetti SalesOrderDetail vengono caricati in modo esplicito per l'oggetto SalesOrderHeader specificato:

' Load the items for the order if not already loaded.
If Not order.SalesOrderDetail.IsLoaded Then
    order.SalesOrderDetail.Load()
End If
// Load the items for the order if not already loaded.
if (!order.SalesOrderDetail.IsLoaded)
{
    order.SalesOrderDetail.Load();
}
NoteNota

Quando si chiama il metodo Load durante un'enumerazione foreach (C#) o For Each (Visual Basic), Object Services tenta di aprire un nuovo lettore dati. Questa operazione non verrà eseguita correttamente a meno che non sia stata attivata la funzionalità MARS (Multiple Active Result Set) specificando multipleactiveresultsets=true nella stringa di connessione. Per ulteriori informazioni, vedere Using Multiple Active Result Sets (MARS) in MSDN. È anche possibile caricare il risultato della query in un insieme List. In questo caso il lettore dati viene chiuso ed è possibile eseguire l'enumerazione sull'insieme per caricare gli oggetti a cui si fa riferimento.

Per ulteriori informazioni, vedere Procedura: caricare in modo esplicito oggetti correlati (Entity Framework).

Esecuzione di una query sugli oggetti correlati

Poiché la classe EntityCollection implementa l'interfaccia IEnumerable, è possibile utilizzare LINQ per eseguire una query sull'insieme di oggetti caricati in EntityCollection restituito da una proprietà di navigazione. È possibile eseguire questa operazione se gli oggetti vengono caricati in modo implicito nel contesto dell'oggetto specificando un percorso della query o se vengono caricati in modo esplicito chiamando il metodo Load.

La chiamata al metodo CreateSourceQuery su un oggetto EntityCollection consente di eseguire una query sugli oggetti correlati senza prima caricare gli oggetti nell'insieme. CreateSourceQuery restituisce un oggetto ObjectQuery che, quando eseguito, restituisce lo stesso set di oggetti restituito dalla chiamata al metodo Load. I metodi del generatore di query possono essere applicati a questa query di oggetto per filtrare ulteriormente gli oggetti caricati nell'insieme. Per ulteriori informazioni, vedere Procedura: eseguire una query sugli oggetti correlati in un oggetto EntityCollection (Entity Framework).

Un oggetto ObjectQuery restituisce i dati EDM come oggetti entità. Quando tuttavia nella proiezione di query viene inclusa una proprietà di navigazione, ObjectQuery restituisce un oggetto DbDataRecord nidificato che contiene gli oggetti correlati. Per ulteriori informazioni, vedere Procedura: spostarsi nelle relazioni utilizzando le proprietà di navigazione (Entity Framework).

Vedere anche

Concetti

Esecuzione di query sui dati come oggetti (Entity Framework)
Query di oggetto (Entity Framework)
Metodi del generatore di query (Entity Framework)