Cargar objetos relacionados (Entity Framework)

En este tema se describen los modelos que puede utilizar para cargar entidades relacionadas. Los tipos de entidad pueden definir propiedades de navegación que representan asociaciones en el modelo de datos. Puede utilizar estas propiedades para cargar entidades relacionadas con la entidad devuelta por la asociación definida. Cuando se generan entidades en función del modelo de datos, se generan propiedades de navegación para las entidades situadas en ambos extremos de una asociación. Estas propiedades de navegación devuelven una referencia en el extremo "uno" de una relación de uno a uno o de una relación de varios a uno, o una colección 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 Propiedades de navegación y Definir y administrar relaciones (Entity Framework).

Los siguientes modelos describen las distintas maneras en que se pueden cargar entidades relacionadas:

Modelo de carga Descripción

Se especifica en la consulta

Puede crear una consulta Entity SQL o LINQ to Entities que navegue explícitamente en las relaciones mediante propiedades de navegación. Al ejecutar este tipo de consulta, se devuelven las entidades relacionadas que están incluidas como propiedades de navegación en la proyección más externa de la consulta. Para obtener más información, vea

Cómo navegar por las relaciones mediante propiedades de navegación (Entity Framework).

Carga explícita

La carga explícita de entidades en ObjectContext requiere varias acciones de ida y vuelta a la base de datos y puede que requiera varios conjuntos de resultados activos, pero la cantidad de datos devueltos se limita solo a las entidades que se cargan. Use el método Load en EntityCollection o EntityReference o bien el método LoadProperty en ObjectContext para recuperar explícitamente las entidades relacionadas del origen de datos. Cada llamada al método Load abre una conexión a la base de datos para recuperar la información relacionada. Esto garantiza que una consulta nunca se ejecute sin una solicitud explícita de la entidad relacionada. La carga explícita es el comportamiento predeterminado de Entity Framework .

Bb896272.note(es-es,VS.100).gifNota:
Antes de llamar a Load, ya se carga una pequeña cantidad de información sobre la entidad relacionada en ObjectContext.

Para obtener más información, vea la sección Explicitly Loading Related Objects de este tema.

Carga diferida

En este tipo de carga, las entidades relacionadas se cargan automáticamente desde el origen de datos cuando se obtiene acceso a una propiedad de navegación. Con este tipo de carga, tenga presente que cada propiedad de navegación a la que se tiene acceso produce una consulta independiente ejecutada con respecto al origen de datos si la entidad aún no está en ObjectContext.

Para obtener más información, vea la sección Lazy Loading de este tema.

Carga diligente

O bien

Definir las rutas de acceso de la consulta con Include

Si conoce la forma exacta del gráfico de las entidades relacionadas que requiere su aplicación, puede utilizar el método Include en ObjectQuery para definir una ruta de acceso de la consulta que controla qué entidades relacionadas se devuelven como parte de la consulta inicial. Al definir una ruta de acceso de la consulta, solo se precisa una única solicitud en la base de datos para devolver todas las entidades definidas por la ruta de acceso en un conjunto de resultados único; todas las entidades relacionadas del tipo especificado en la ruta de acceso se cargan con cada objeto devuelto por la consulta.

Para obtener más información, vea la sección Defining a Query Path to Shape Query Results de este tema.

Cargar explícitamente objetos entidad relacionados

Para cargar explícitamente entidades 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 de uno a uno, llame al método Load en EntityReference. Si está trabajando con entidades POCO, utilice el método LoadProperty en ObjectContext. Para obtener más información, vea Cargar entidades POCO relacionadas (Entity Framework). El método LoadProperty también se puede utilizar con entidades derivadas de EntityObject. Estos métodos cargan los datos de objeto relacionados en el contexto del objeto. Cuando una consulta devuelve resultados, se puede enumerar mediante la colección de objetos usando un bucle foreach (For Each...Next en Visual Basic) y llamar condicionalmente al método Load en las propiedades EntityReference y EntityCollection para cada entidad de los resultados.

Bb896272.note(es-es,VS.100).gifNota:
Cuando se llama al método Load durante una enumeración foreach (C#) o For Each (Visual Basic), Entity Framework 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 las entidades a las que se hace referencia.

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

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

Para especificar la ruta de acceso de una consulta, pase una representación de cadena del gráfico de objetos al método Include en ObjectQuery. Esta ruta de acceso especifica qué entidades relacionadas se van a devolver cuando se ejecuta una consulta de objeto. Por ejemplo, la ruta de acceso de una consulta definida en una consulta para objetos Contact garantiza la devolución de cada SalesOrderHeader y SalesOrderDetail relacionado. Esto se muestra en la siguiente consulta:

' Define a LINQ query with a path that returns 
' orders and items for a contact. 
Dim contacts = (From contact In context.Contacts.Include("SalesOrderHeaders.SalesOrderDetails") _
    Select contact).FirstOrDefault()
// Define a LINQ query with a path that returns 
// orders and items for a contact.
var contacts = (from contact in context.Contacts
              .Include("SalesOrderHeaders.SalesOrderDetails")
                select contact).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 consulta ObjectQuery para incluir entidades 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.SalesOrderHeaders.Include("SalesOrderDetails").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.SalesOrderHeaders.Include("SalesOrderDetails").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 ocurre debido a que se requieren una o varias combinaciones para devolver objetos relacionados en una sola consulta, lo que produce datos redundantes para cada entidad relacionada que se devuelve desde el origen de datos. Esta complejidad es mayor en consultas con un modelo 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 consulta ObjectQuery. 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 o habilitando la carga aplazada. Si después de optimizar una consulta compleja todavía obtiene tiempos de espera frecuentes, puede aumentar el valor de tiempo de espera estableciendo la propiedad CommandTimeout.

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

Cargar objetos entidad de forma diferida

Entity Framework admite la carga diferida de entidades relacionadas. En el motor en tiempo de ejecución de Entity Framework , el valor predeterminado de la propiedad LazyLoadingEnabled de una instancia de ObjectContext es false. Sin embargo, si utiliza las herramientas de Entity Framework para crear un nuevo modelo y las clases generadas correspondientes, LazyLoadingEnabled se establece en true en el constructor del contexto de objetos. Si se ha habilitado la carga diferida, las entidades relacionadas no se cargan desde el origen de datos hasta que el descriptor de acceso get de una propiedad de desplazamiento tiene acceso a ellas mediante programación. Para deshabilitar la carga diferida, establezca la propiedad LazyLoadingEnabled en false en la instancia de ObjectContextOptions devuelta por la propiedad System.Data.Objects.ObjectContext.ContextOptions.

La carga diferida se puede usar junto con la carga diligente. De esta manera, se puede definir un gráfico de datos base usando rutas de acceso de consulta, y las entidades relacionadas adicionales no incluidas en las rutas de acceso de consulta originales se pueden cargar según sea necesario. Para obtener más información, vea Cómo: Utilizar la carga diferida para cargar objetos relacionados (Entity Framework).

Debe tenerse en cuenta lo siguiente al usar la carga diferida:

  • La carga diferida es compatible con las propiedades de navegación que devuelven una entidad única (como EntityReference) y una colección de entidades (como EntityCollection).

  • Si se habilita la carga diferida y ya se ha cargado una entidad relacionada, no se cargará de nuevo.

  • La carga diferida se admite en las entidades con un estado Detached. En este caso, los objetos relacionados también se devuelven con un estado Detached.

  • El comportamiento de la carga diferida viene determinado por la instancia de ObjectContext usada para recuperar el objeto del origen de datos (incluso si la entidad se cargó con la opción NoTracking de la enumeración MergeOption) o a la que se agregó o adjuntó el objeto. Por ello, el comportamiento de la carga diferida no se puede cambiar una vez se ha eliminado este contexto, y cualquier operación subsiguiente de carga diferida producirá un error.

  • Al serializar las entidades, considere la posibilidad de deshabilitar la carga diferida. De lo contrario, dicha carga se activará y es posible que la entidad serializada incluya más datos de los previstos.

Se aplican consideraciones adicionales si se usa la carga diferida con entidades POCO. Para obtener más información, vea Cargar entidades POCO relacionadas (Entity Framework).

Consultar objetos entidad relacionados

Llame al método CreateSourceQuery en una colección EntityCollection para consultar los objetos relacionados sin cargar primero los objetos en la colección. CreateSourceQuery devuelve una clase ObjectQuery que, cuando se ejecuta, devuelve el mismo conjunto de objetos que una llamada al método Load. Los métodos del generador de consultas se pueden aplicar a esta consulta de los objetos 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).

Una consulta ObjectQuery devuelve los datos de entidad como entidades. Sin embargo, cuando se incluye una propiedad de navegación en la proyección más externa de la consulta, la consulta también devuelve las entidades relacionadas a las que ha tenido acceso la navegación. Para obtener más información, vea Cómo navegar por las relaciones mediante propiedades de navegación (Entity Framework).

Consideraciones de rendimiento

A la hora de elegir un modelo para cargar las entidades relacionadas, tenga en cuenta el comportamiento de cada enfoque con respecto al número y control de tiempo de las conexiones realizadas con el origen de datos con respecto a la cantidad de datos devueltos por una consulta única y la complejidad de utilizarla. La carga diligente devuelve todas las entidades relacionadas junto con las entidades consultadas en una única consulta. Esto significa que, aunque solo haya una conexión con el origen de datos, se devuelve una cantidad mayor de datos en la consulta inicial. Asimismo, las rutas de acceso de la consulta producen una consulta más compleja debido a las combinaciones adicionales que se requieren en la consulta que se ejecuta con respecto al origen de datos.

La carga explícita y la carga diferida permiten posponer la solicitud de los datos de objetos relacionados hasta que realmente se necesiten dichos datos. Esto produce una consulta inicial menos compleja que devuelve menos datos totales. Sin embargo, cada carga sucesiva de un objeto relacionado establece una conexión con el origen de datos y ejecuta una consulta. En el caso de una carga diferida, esta conexión se produce siempre que se tiene acceso a una propiedad de navegación y la entidad relacionada todavía no está cargada. Si desea saber qué entidades relacionadas devuelve la consulta inicial o controlar los intervalos de carga de dichas entidades desde el origen de datos, considere la posibilidad de deshabilitar la carga diferida. La carga diferida está habilitada en el constructor del contexto del objeto generado por Entity Framework .

Para obtener más información, vea Consideraciones de rendimiento (Entity Framework).

Vea también

Conceptos

Consultar un modelo conceptual (Entity Framework)
Consultas de objeto (Entity Framework)
Métodos del Generador de consultas (Entity Framework)