lazyloadingenabled lazy framework first code c# entity-framework orm entity-framework-6 lazy-loading

c# - lazy - Carga ansiosa, perezosa y explícita en EF6



entity framework lazy loading vs eager loading (3)

Si este pequeño currículum es cierto?

Sí.

Si es cierto, ¿cuál es la diferencia entre la carga ansiosa y explícita?

La carga ansiosa es lo opuesto a la carga diferida , pero la carga explícita es similar a la carga diferida , excepto que: recupera explícitamente los datos relacionados en el código; no sucede automáticamente cuando accede a una propiedad de navegación. Puede cargar datos relacionados manualmente obteniendo la entrada del administrador de estado de objeto para una entidad y llamando al método Collection.Load para colecciones o al método Reference.Load para propiedades que contienen una sola entidad.

De techblog :

Carga ansiosa:

La carga ansiosa es lo opuesto a la carga diferida, que es: El proceso de cargar un conjunto específico de objetos relacionados junto con los objetos que se solicitaron explícitamente en la consulta.

Carga explícita:

La carga explícita se define como: cuando una consulta devuelve objetos, los objetos relacionados no se cargan al mismo tiempo. De manera predeterminada, no se cargan hasta que se solicite explícitamente utilizando el método Load en una propiedad de navegación.

Y:

Si uso la carga diferida y llamo, por ejemplo, dpc_gestion.dpc_participant , ¿se cargan las propiedades de navegación o dpc_gestion.dpc_participant una excepción?

No obtienes ninguna excepción y las propiedades de navegación deberían cargarse.

¿Hay algún caso en que la carga ansiosa o la carga explícita fueran mejores que la carga lenta en el rendimiento y la capacidad de respuesta?

La carga ansiosa suele ser más eficiente cuando necesita los datos relacionados para todas las filas recuperadas de la tabla primaria. Y también cuando las relaciones no son demasiado, la carga ansiosa será una buena práctica para reducir más consultas en el servidor. Pero cuando sabe que no necesitará una propiedad al instante, la carga diferida puede ser una buena opción. Y también la carga ansiosa es una buena opción en una situación en la que su contexto db se eliminaría y la carga diferida ya no podría tener lugar. Por ejemplo, considere lo siguiente:

public List<Auction> GetAuctions() { using (DataContext db = new DataContext()) { return db.Auctions.ToList(); } }

Después de llamar a este método, no puede cargar la entidad relacionada perezosamente porque el db está dispuesto y, por lo tanto, la carga ansiosa sería una mejor opción aquí.

Una cosa más a tener en cuenta es: la carga diferida producirá varias solicitudes SQL mientras que Eager carga los datos de carga con una solicitud. La carga ansiosa también es una buena opción para resolver el problema de las selecciones n + 1 en los ORM. Echa un vistazo a esta publicación: ¿Cuál es el problema de las selecciones n + 1?

He leído este tutorial y este article pero no entiendo exactamente el uso de cada tipo de carga.

Yo explico

Tengo este POCO:

public partial class dpc_gestion { public dpc_gestion() { this.ass_reunion_participant = new HashSet<ass_reunion_participant>(); this.dpc_participant = new HashSet<dpc_participant>(); this.dpc_reunion = new HashSet<dpc_reunion>(); } public int dpc_id_pk { get; set; } public Nullable<int> dpc_id_gdp_fk { get; set; } public Nullable<int> dpc_id_theme { get; set; } public int dpc_id_animateur_fk { get; set; } public Nullable<System.DateTime> dpc_date_creation { get; set; } public Nullable<System.DateTime> dpc_date_fin { get; set; } public Nullable<System.DateTime> dpc_date_engag_anim { get; set; } public Nullable<bool> dpc_flg_let_engag_anim { get; set; } public Nullable<bool> dpc_flg_fsoins_anim { get; set; } public virtual ICollection<ass_reunion_participant> ass_reunion_participant { get; set; } public virtual theme_dpc theme_dpc { get; set; } public virtual gdp_groupe_de_pair gdp_groupe_de_pair { get; set; } public virtual ICollection<dpc_participant> dpc_participant { get; set; } public virtual ICollection<dpc_reunion> dpc_reunion { get; set; } }

Entendí esto:

  1. Para carga diferida: debido a que la carga es diferida, si llamo a dbset dpc_gestion , no se dpc_gestion todas las propiedades de navegación. Este tipo de carga es el mejor en rendimiento y capacidad de respuesta. Está habilitado de forma predeterminada y si quisiera volver a habilitarlo tengo que configurar:

    context.Configuration.ProxyCreationEnabled = true; context.Configuration.LazyLoadingEnabled = true;

  2. Para la carga ansiosa No es perezosa: cargó todas las propiedades de navegación cuando cargo dpc_gestion . Las propiedades de navegación se pueden cargar utilizando el método de include . Para habilitar este tipo de carga:

    context.Configuration.LazyLoadingEnabled = false;

  3. Para la carga explícita Es como la carga ansiosa pero usamos el método Load lugar de include .

Entonces me gustaría saber:

  1. Si este pequeño currículum es cierto?
  2. Si es cierto, ¿cuál es la diferencia entre la carga ansiosa y explícita?
  3. Si uso la carga diferida y llamo, por ejemplo, dpc_gestion.dpc_participant , ¿se cargan las propiedades de navegación o dpc_gestion.dpc_participant una excepción?
  4. ¿Hay algún caso en que la carga ansiosa o la carga explícita fueran mejores que la carga lenta en el rendimiento y la capacidad de respuesta?

Gracias


Aquí aprenderá cómo cargar entidades relacionadas en un gráfico de entidad explícitamente. La carga explícita es válida en EF 6 y EF Core ambos.

Incluso con la carga diferida deshabilitada (en EF 6), todavía es posible cargar diferidamente entidades relacionadas, pero debe hacerse con una llamada explícita. Use el método Load() para cargar entidades relacionadas explícitamente. Considere el siguiente ejemplo.

using (var context = new SchoolContext()) { var student = context.Students .Where(s => s.FirstName == "Bill") .FirstOrDefault<Student>(); context.Entry(student).Reference(s => s.StudentAddress).Load(); // loads StudentAddress context.Entry(student).Collection(s => s.StudentCourses).Load(); // loads Courses collection }

En el ejemplo anterior, context.Entry(student).Reference(s => s.StudentAddress).Load() carga la entidad StudentAddress . El método Reference() se usa para obtener un objeto de la propiedad de navegación de referencia especificada y el método Load() carga explícitamente.

De la misma manera, context.Entry(student).Collection(s => s.Courses).Load() carga la propiedad de navegación de colección Courses de la entidad Student. El método Collection() obtiene un objeto que representa la propiedad de navegación de la colección.

El método Load() ejecuta la consulta SQL en la base de datos para obtener los datos y completar la referencia especificada o la propiedad de colección en la memoria, como se muestra a continuación.
Consulta (): también puede escribir consultas LINQ-to-Entities para filtrar los datos relacionados antes de cargar. El método Query () nos permite escribir más consultas LINQ para las entidades relacionadas para filtrar los datos relacionados.

using (var context = new SchoolContext()) { var student = context.Students .Where(s => s.FirstName == "Bill") .FirstOrDefault<Student>(); context.Entry(student) .Collection(s => s.StudentCourses) .Query() .Where(sc => sc.CourseName == "Maths") .FirstOrDefault(); }

En el ejemplo anterior, .Collection(s => s.StudentCourses).Query() nos permite escribir más consultas para la entidad StudentCourses .


Pregunta 1 y 2:

Su explicación de la carga diferida y la carga ansiosa es correcta.
El uso de carga explícita es un poco diferente de lo que describiste.

EntityFramework devuelve objetos EntityFramework , que esencialmente contienen la consulta a la base de datos. Pero estos no se ejecutan hasta la primera vez que se enumeran.
Load ejecuta la consulta para que sus resultados se almacenen localmente.
Llamar a Load es lo mismo que llamar a ToList y tirar esa List , sin tener la sobrecarga de crear la List .

Pregunta 3:

Si utiliza la carga diferida, EntityFramework se encargará de cargar la propiedad de navegación por usted, por lo que no obtendrá una excepción.
Tenga en cuenta que esto puede llevar un tiempo y hacer que su aplicación no responda .

Pregunta 4:

En casos desconectados (p. Ej., Aplicación de red), no puede usar la carga diferida , porque estos objetos se traducen en DTO y luego EntityFramework no los rastrea.

Además, si sabe que va a usar una propiedad de navegación , es una buena práctica cargarla con entusiasmo , para que no tenga que esperar hasta que se carguen de la base de datos.
Por ejemplo, supongamos que almacena el resultado en una lista y lo vincula a una cuadrícula de datos WPF. Si DataGrid accede a una propiedad que aún no está cargada, el usuario experimenta un tiempo de espera notable hasta que se muestre esa propiedad. Además, la aplicación no responderá durante el tiempo de carga (si no carga de forma asincrónica).