Entendiendo Lazy Loading, Eager Loading y Explicit Loading en Entity Framework Core

Bienvenidos a todos a un nuevo post dentro del curso de entity framework core en el que hoy vamos a ver las diferentes opciones que tenemos en entity framework core para cargar datos relacionados dependiendo de las necesidades de tu aplicación. 

 

 

Recuerda que todo este código está disponible en GitHub, antes de continuar con este post, recomiendo mirar el de las relaciones en Entity Framework Core.

 

 

1 - Qué es  Eager loading en entity framework core

Si bien es cierto que no hemos visto directamente qué es Eager loading, sí que lo hemos visto de forma indirecta. Ya que el Eager loading consiste en la carga directa (la verdad no se muy bien cómo traducir esto) de los datos que están relacionados con tu entidad en la misma consulta que consultamos la entidad principal. 

 

En Entity framework Core esto se consigue cuando en el el dbSet utilizamos un .Include():

[HttpGet("eager-loading")]
public async Task<List<User>> EagerLoading()
    => await _context.Users
        .Include(a => a.Wokringexperiences)
        .ToListAsync();

En este escenario, al cargar user estamos incluyendo las working experiences en la misma consulta, lo que en SQL se traduce en un join

 

 

2 - Qué es lazy loading en entity framework core

Lazy loading o carga perezosa también lo vimos de pasada cuando explique IQueryable aqui es cuando cargamos una entidad principal cargada, pero los datos no se cargan hasta que accedemos a dicha propiedad de la entidad.

 

Antes de hacer el cambio en el código, tenemos que tener en cuenta que desde .netcore 3, tenemos que instalar el paquete Microsoft.EntityFrameworkCore.Proxies dentro del proyecto, ya que ya no vienen por defecto. 

En las opciones cuando incluimos el DBContext debemos especificar la siguiente configuración:

services.AddDbContext<CursoEfContext>(options=>
    options
    .UseLazyLoadingProxies() // <----- HERE
    .UseMySQL("server=127.0.0.1;port=4306;database=cursoEF;user=root;password=cursoEFpass"));

Y finalmente en la entidad, debemos especificarla como virtual:

public virtual ICollection<Wokringexperience> Wokringexperiences { get; set; }

 

Ahora sí, ya podemos ir a la lógica como tal, en nuestro caso, cambiamos el código al siguiente, y la parte donde consultamos las working experiences no se va a ejecutar hasta que llegamos a la línea donde accedemos a ella:

[HttpGet("lazy-loading/{userId}")]
public async Task<User?> LazyLoading(int userId)
{
    User? user = await _context.Users.FirstOrDefaultAsync(a => a.Id == userId);

    if (user is not null)
    {
        var experiences = user.Wokringexperiences; // <---- HERE
        if (experiences is not null && experiences.Any())
        {
            Console.WriteLine("this user has experiences");
        }
    }
    return user;
}

De primeras esta solución parece la mejor, pero hay que tener cuidado, ya que una consulta con un join, aunque tenga muchos registros, es muy posible que sea más rápida que muchas consultas pequeñas, así, qué, dependiendo lo que queramos o estemos haciendo, tendremos que tener cabeza a la hora de elegir Eager loading o Lazy loading.

 

Esto son las consultas que se ejecutan del código anterior:

example lazy loading csharp

  • Nota: No confundir Lazy Loading de Entity framework core con Lazy<T> de .NET.

 

 

3 - Explicit loading en Entity Framework Core

Finalmente cuando hacemos explicit loading o carga explícita lo que hacemos es muy similar a lazy loading, ya que no cargamos los datos de forma automática, sino que tenemos que especificarlo de forma explícita.

Por ejemplo si cargamos un usuario, para cargar sus workingExperiences lo hacemos de la siguiente forma: 

[HttpGet("explicit-loading/{userId}")]
public async Task<User?> ExplicitLoading(int userId)
{
    User? user = await _context.Users.FirstOrDefaultAsync(a => a.Id == userId);

    if (user is not null)
    {
        await _context.Entry(user)
            .Collection(a => a.Wokringexperiences)
            .LoadAsync(); // <----- HERE
        
        if (user.Wokringexperiences is not null && user.Wokringexperiences.Any())
        {
            Console.WriteLine("this user has experiences");
        }
    }
    return user;
}

Como ves, estamos indicando la colección a la que hace referencia y posteriormente cargando los datos con el método Load() / LoadAsync(). Igual que en el lazy loading, se hace una consulta separada.

 

Una cosilla a tener en cuenta es que Explicit loading se puede saltar el lazy loading cuando está deshabilitado (o no tenemos el proxy habilitado), así que te puede servir como hack en ciertos escenarios. 

 

 

Conclusión

 

Como con todas las cosas en el desarrollo de software, la elección entre Lazy Loading, Eager Loading y Explicit Loading dependerá de tu situación y requerimientos particulares. Espero que este post te pueda ayudar a tomar una decisión!

 


Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2024 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café