Carga diferida vs carga ansiosa

79

La carga diferida en Entity Framework es el fenómeno predeterminado que ocurre para cargar y acceder a las entidades relacionadas. Sin embargo, la carga ansiosa se refiere a la práctica de forzar todas estas relaciones. Me he encontrado con la pregunta de en qué situación la carga ansiosa podría ser más beneficiosa que la carga diferida. Preguntando esto, porque es obvio que la carga diferida es más amigable con los recursos, e incluso si usamos elToList() método, aún podemos aprovechar el comportamiento de carga diferida. Sin embargo, pensé que tal vez la carga diferida aumenta la cantidad de solicitudes a la base de datos real y tal vez es por eso que a veces los desarrolladores usan elInlcudemétodo para forzar la carga de todas las relaciones. Por ejemplo, cuando se usa el andamio automático de Visual Studio en MVC 5, el método Index que se crea automáticamente en el controlador siempre usa Eager Loading, y siempre me he preguntado por qué Microsoft usa Eager Loading de forma predeterminada en ese caso.

Agradecería que alguien me explicara en qué situación la carga ansiosa sería más beneficiosa que la carga diferida, y por qué la usamos mientras hay algo más amigable con los recursos como la carga diferida.

Arnold Zahrneinder
fuente
8
Imagine una situación en la que su contexto de base de datos se eliminaría y la carga diferida ya no podría tener lugar. Entonces la carga ansiosa es beneficiosa.
Trascendente
2
He visto muchos proyectos fallar debido a problemas de rendimiento debido al problema "N + 1 Select" que ocurrirá más rápido cuando se realiza la carga diferida, así que asegúrese de buscarlo
David DV

Respuestas:

80

Creo que es bueno categorizar relaciones como esta

Cuando usar la carga ansiosa

  1. En "un lado" de las relaciones uno a muchos que seguro se utilizan en todas partes con la entidad principal. como propiedad de usuario de un artículo. Propiedad de categoría de un producto.
  2. Generalmente, cuando las relaciones no son demasiadas y la carga ansiosa será una buena práctica para reducir más consultas en el servidor.

Cuando usar la carga diferida

  1. Casi en todos los "lados de la colección" de las relaciones de uno a varios. como artículos de usuario o productos de una categoría
  2. Usted sabe exactamente que no necesitará una propiedad al instante.

Nota: como dijo Transcendent, puede haber un problema de eliminación con la carga diferida.

farid bekran
fuente
5
No solo estaba tratando de responder lo mismo. Utilice la carga diferida cuando sepa que rara vez necesitará utilizar los datos relacionados. Pero cuando sepa que querrá ciertos datos relacionados con bastante frecuencia, utilice la carga ansiosa.
Ghasan
¿Puedo usar ambos juntos?, por ejemplo, si la entidad está casi relacionada con otra, puedo incluirla mediante una carga ansiosa, y otras entidades relacionadas serán mediante una carga diferida
Ahmad Alaa
28

Carga ansiosa: Carga ansiosa lo ayuda a cargar todas las entidades necesarias a la vez. es decir, los objetos relacionados (objetos secundarios) se cargan automáticamente con su objeto principal.

Cuándo usar:

  1. Utilice Carga ansiosa cuando las relaciones no sean demasiadas. Por lo tanto, la carga ansiosa es una buena práctica para reducir más consultas en el servidor.
  2. Utilice Eager Loading cuando esté seguro de que utilizará entidades relacionadas con la entidad principal en todas partes.

Carga diferida : en caso de carga diferida, los objetos relacionados (objetos secundarios) no se cargan automáticamente con su objeto principal hasta que se solicitan. De forma predeterminada, LINQ admite la carga diferida.

Cuándo usar:

  1. Utilice la carga diferida cuando utilice colecciones de uno a varios.
  2. Utilice la carga diferida cuando esté seguro de que no está utilizando entidades relacionadas al instante.

NOTA: Entity Framework admite tres formas de cargar datos relacionados: carga ansiosa, carga diferida y carga explícita.

Materia oscura
fuente
Estoy realmente confundido acerca de la carga impaciente y perezosa. ¿Podrías hacerme entender, por favor? Por referencia de Google, diría esto sobre la carga diferida. "Debe usar una palabra clave virtual cuando desee cargar datos con carga diferida. La carga diferida es el proceso mediante el cual una entidad o colección de entidades se carga automáticamente desde la base de datos la primera vez que se accede a ella. 7 de enero de 2016" es que el Lo mismo que dijiste sobre la carga diferida.
Rykamol
@rykamol Intenta entenderlo como un patrón de diseño. Puede consultar desde aquí para una mejor comprensión: Carga ansiosa - entityframeworktutorial.net/… , Carga diferida - entityframeworktutorial.net/… , Carga explícita - entityframeworktutorial.net/EntityFramework4.3/…
Dark Matter
20

La carga diferida producirá varias llamadas SQL, mientras que la carga ansiosa puede cargar datos con una llamada "más pesada" (con uniones / subconsultas).

Por ejemplo, si hay un ping alto entre su web y los servidores SQL, optaría por la carga ansiosa en lugar de cargar elementos relacionados 1 por 1 con carga diferida.

serhiyb
fuente
¿puedo usar ambos juntos?
Ahmad Alaa
12

Considere la siguiente situación

public class Person{
    public String Name{get; set;}
    public String Email {get; set;}
    public virtual Employer employer {get; set;}
}

public List<EF.Person> GetPerson(){
    using(EF.DbEntities db = new EF.DbEntities()){
       return db.Person.ToList();
    }
}

Ahora, después de llamar a este método, ya no puede cargar la Employerentidad de forma diferida . ¿Por qué? porque el dbobjeto está desechado. Entonces tienes que hacer Person.Include(x=> x.employer)para forzar que se cargue.

Trascendente
fuente
3
Sí, ese es un ejemplo cuando la carga diferida no ayuda. Otra cosa es que crear DbContext cada vez que necesite algunos datos es una mala forma. Si tiene algún contenedor de IoC, su DbContext vivirá junto con Request (en el caso de aplicaciones web).
Miroslav Holec
@MiroslavHolec: Brillante, eso es lo que realmente hago usando Ninject. Lo que acaba de mencionar es realmente muy, muy agradable.
Trascendente
8

Carga ansiosa Cuando esté seguro de que desea obtener varias entidades a la vez, por ejemplo, debe mostrar el usuario y los detalles del usuario en la misma página, entonces debe ir con la carga ansiosa. La carga ansiosa hace un solo golpe en la base de datos y carga las entidades relacionadas.

Carga diferida Cuando tiene que mostrar a los usuarios solo en la página y, al hacer clic en los usuarios, debe mostrar los detalles del usuario, debe utilizar la carga diferida. La carga diferida genera múltiples visitas para cargar las entidades relacionadas cuando enlaza / itera entidades relacionadas.

Alguacil
fuente
2

Carga diferida : es bueno cuando se maneja con paginación, como en la carga de la página, aparece una lista de usuarios que contiene 10 usuarios y, a medida que el usuario se desplaza hacia abajo en la página, una llamada de API trae los siguientes 10 usuarios. Es bueno cuando no desea cargar datos completos en una vez, ya que llevaría más tiempo y daría una mala experiencia al usuario.

Carga ansiosa : es bueno como sugirieron otras personas cuando no hay muchas relaciones y obtienen datos completos de una sola vez en una sola llamada a la base de datos

Iqra Abdul Rauf
fuente
-1

Es mejor utilizar la carga ansiosa cuando sea posible, porque optimiza el rendimiento de su aplicación.

ex-:

Eager loading

var customers= _context.customers.Include(c=> c.membershipType).Tolist();

lazy loading

En el modelo, el cliente debe definir

Public virtual string membershipType {get; set;}

Entonces, cuando se consulta la carga diferida, la carga de todos los objetos de referencia es mucho más lenta, pero la carga ansiosa de la consulta y selecciona solo el objeto que es relevante.

Nuwan Dhanushka
fuente
use herramientas de diagnóstico de rendimiento como Glimpse y verifique cómo funcionan ambas mientras la carga diferida tiene múltiples conexiones y las consultas ansiosas solo tienen una. Los he comprobado prácticamente, por favor mencione por qué dice eso mal.
Nuwan Dhanushka
#FakeCaleb ha eliminado su comentario
Nuwan Dhanushka
Un mod eliminó mi comentario, no vi el sentido de continuar esta conversación ya que de todos modos
entendiste
No mencionaste el punto exacto y dijiste que mi comentario es completamente engañoso, si mencionas cuáles son los puntos que son incorrectos, también puedo aprender.
Nuwan Dhanushka
Creo que, debido a la redacción, connotas que la carga ansiosa es mejor que la carga diferida debido al rendimiento. Puedo pensar en escenarios donde esto no es cierto.
FakeCaleb
-2
// Using LINQ and just referencing p.Employer will lazy load
// I am not at a computer but I know I have lazy loaded in one
// query with a single query call like below.
List<Person> persons = new List<Person>();
using(MyDbContext dbContext = new MyDbContext())
{
    persons = (
        from p in dbcontext.Persons
        select new Person{
            Name = p.Name,
            Email = p.Email,
            Employer = p.Employer
        }).ToList();
}
Matt Empringham
fuente
1
Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y es posible que esas personas no conozcan los motivos de su sugerencia de código.
He Yifei 何 一 非
1
Esta respuesta no aborda la pregunta de los OP en absoluto. OP no pregunta sobre cómo hacerlo Lazy loading, pregunta sobre "cuándo Lazy loadingy cuándo usarlo Eager Loading"
Mischa