Dar forma a los resultados de la consulta (Entity Framework)

Al ejecutar una consulta, sólo se devuelven los objetos que se solicitan específicamente en la consulta. Por ejemplo, cuando una consulta con el modelo Adventure Works Sales devuelve objetos Customer, no se devuelven de forma predeterminada los objetos SalesOrderHeader relacionados, aunque haya una relación entre Customer y SalesOrderHeader. Este comportamiento garantiza que la aplicación conozca siempre el ámbito de los datos que se devuelven de una consulta de objeto. De forma predeterminada, siempre se devuelven los objetos de relación que representan asociaciones entre tipos de entidad. Cuando los objetos se generan en función del esquema conceptual del modelo EDM, se generan propiedades de navegación para objetos entidad en ambos extremos de una asociación. Estas propiedades de navegación devuelven EntityReference en el extremo "uno" de una relación de uno a uno o de una relación de varios a uno, o EntityCollection en el extremo "varios" de una relación de uno a varios o de una relación de varios a varios. Para obtener más información, vea Relaciones del Entity Data Model.

Puede crear una consulta Entity SQL o LINQ to Entities que navegue explícitamente en estas relaciones utilizando propiedades de navegación. Para obtener más información, vea Cómo navegar por las relaciones mediante propiedades de navegación (Entity Framework). Sin embargo, no necesita navegar explícitamente en relaciones en la consulta para dar forma a los resultados de la misma. Hay otras dos maneras de extender los resultados de una consulta para cargar también los objetos a que se hace referencia: se pueden especificar las rutas de la consulta o se pueden cargar explícitamente los objetos relacionados mediante propiedades de navegación. Para ejercer un control todavía mayor sobre los resultados, se puede definir una ruta de la consulta y, a continuación, cargar explícitamente sólo los objetos relacionados seleccionados.

Al considerar que opción se debe utilizar, sea consciente de que hay un intercambio entre el número de solicitudes con la base de datos y la cantidad de datos devueltas en una consulta única. Las rutas de la consulta definen el gráfico de los objetos devueltos por una consulta. Al definir la ruta de una consulta, sólo se requiere una solicitud única con la base de datos para que se devuelvan todos los objetos definidos por la ruta en un conjunto de resultados único. La carga explícita de objetos requiere varios viajes de ida y vuelta (round trips) a la base de datos y puede que requiera varios conjuntos de resultados activos, pero la cantidad de datos devueltos se limita sólo a los objetos que se han cargado.

Definir la ruta de una consulta para dar forma a los resultados de la consulta

Para especificar la ruta de una consulta, pase una representación de cadena del gráfico de objetos al método Include en ObjectQuery. Esta ruta especifica qué objetos relacionados se han de devolver cuando se ejecuta una consulta de objeto. Por ejemplo, la ruta de una consulta definida en una consulta para objetos Contact garantiza la devolución de cada SalesOrderHeader y SalesOrderDetail relacionado. Esto se muestra en las consultas siguientes que utilizan LINQ to Entities, Entity SQL y métodos del generador de consultas.

  • 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();
```
  • Métodos del generador de consultas

    ' 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();
    

Las consideraciones siguientes se aplican al definir las rutas de consultas:

  • Se pueden usar rutas de consultas con métodos del generador de consultas y con consultas LINQ.

  • Cuando se llama al método Include, la ruta de la consulta solo es válida en la instancia devuelta de ObjectQuery. Otras instancias de ObjectQuery y el contexto del objeto en sí no se ven afectados.

  • Dado que el método Include devuelve el objeto de consulta, puede llamar varias veces a este método en una ObjectQuery para incluir objetos de varias relaciones, como en el ejemplo siguiente:

    ' 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");
    
  • El uso de rutas de consultas puede dar lugar a la ejecución de comandos complejos que se ejecutan con el origen de datos en consultas de objeto aparentemente simples. Esto se produce porque se requieren una o más combinaciones para la devolución de objetos relacionados en una consulta única. Esta complejidad es mayor en consultas con un modelo EDM complejo, como una entidad con herencia o una ruta que incluye relaciones de varios a varios. Use el método ToTraceString para ver el comando que se generará mediante una ObjectQuery. Para obtener más información, vea Consultas de objeto [Entity Framework]. Cuando la ruta de una consulta incluye demasiados objetos relacionados o cuando los objetos contienen demasiados datos de fila, es posible que el origen de datos no pueda completar la consulta. Esto se produce si la consulta requiere un almacenamiento temporal intermedio que supera las capacidades del origen de datos. Cuando esto se produce, se puede reducir la complejidad de la consulta del origen de datos cargando explícitamente los objetos relacionados.

Para obtener más información, vea Cómo usar rutas de la consulta para dar forma a los resultados (Entity Framework).

Cargar explícitamente los objetos relacionados

Para cargar explícitamente los objetos relacionados, se debe llamar al método Load en el extremo relacionado devuelto por la propiedad de navegación. En una relación de uno a varios, llame al método Load en EntityCollection, y para una relación uno a uno, llame al método Load en EntityReference. Esto carga los datos de objetos relacionados en el contexto del objeto. Cuando una consulta devuelve una colección de objetos, puede enumerarlos en la colección y llamar al método Load para cargar los objetos relacionados de cada objeto en la colección, como cada objeto SalesOrderDetail que pertenece a un objeto SalesOrderHeader. En el ejemplo siguiente, los objetos SalesOrderDetail se cargan explícitamente para el objeto SalesOrderHeader especificado:

' 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();
}
Nota

Cuando se llama al método Load durante una enumeración foreach (C#) o For Each (Visual Basic), Servicios de objeto intenta abrir un nuevo lector de datos. Si no ha especificado multipleactiveresultsets=true en la cadena de conexión para habilitar varios conjuntos de resultados activos, se producirá un error durante esta operación. Para obtener más información, vea Using Multiple Active Result Sets (MARS) en MSDN. También puede cargar el resultado de la consulta en una colección List, lo que cierra el lector de datos y permite realizar la enumeración en la colección para cargar los objetos a los que se hace referencia.

Para obtener más información, vea Cómo cargar explícitamente objetos relacionados (Entity Framework).

Consultar los objetos relacionados

Dado que la clase EntityCollection implementa la interfaz IEnumerable, puede utilizar LINQ para consultar la colección de objetos cargados en la EntityCollection devuelta por una propiedad de navegación. Esto funciona si los objetos se cargan implícitamente en el contexto del objeto especificando la ruta de una consulta o se cargan explícitamente llamando al método Load.

Llamar al método CreateSourceQuery en una EntityCollection permite consultar los objetos relacionados sin cargar primero los objetos en la colección. CreateSourceQuery devuelve una ObjectQuery que, cuando se ejecuta, devuelve el mismo conjunto de objetos que si se llama al método Load. Los métodos del generador de consultas se pueden aplicar a esta consulta de objeto para filtrar todavía más los objetos cargados en la colección. Para obtener más información, vea Cómo consultar objetos relacionados en una EntityCollection (Entity Framework).

ObjectQuery devuelve los datos del modelo EDM como objetos entidad. Sin embargo, cuando una propiedad de navegación está incluida en la proyección de consultas, ObjectQuery devuelve un DbDataRecord anidado que contiene los objetos relacionados. Para obtener más información, vea Cómo navegar por las relaciones mediante propiedades de navegación (Entity Framework).

Vea también

Conceptos

Consultar datos como objetos (Entity Framework)
Consultas de objeto [Entity Framework]
Métodos del generador de consultas (Entity Framework)