EF Core 2.1 - Usando Lazy Loading

 Hoje veremos como usar o Lazy Loading no Entity Framework Core 2.1.

Em maio passado (maio/2018) foi lançada a versão 2.1 do Entity Framework Core juntamente com a .NET Core 2.1 trazendo algumas novidades.

Uma delas foi a implementação do recurso Lazy Loading que existia nativamente no EF 6 mas que ainda não havia sido implementado no EF Core.

Para quem é não sabe o Lazy Loading ou 'Carregamento preguiçoso' é um recurso onde as entidades relacionadas no modelo de entidades são carregadas nas consultas sob demanda, ou seja, somente quando forem realmente necessárias e isso ocorre quando usamos um First, Find, Single, Find, ToList, ToArray ou quando iteramos usando o foreach ou for/next.

A maneira mais simples para usar o Lazy Loading é :

  1. Instlar o pacote Microsoft.EntityFrameworkCore.Proxies ;
  2. Habilitá-lo com uma chamada para UseLazyLoadingProxies;

Após isso o EF Core, vai habilitar o lazy loading para qualquer propriedade de navegação que pode ser sobrescrita ou seja a propriedade de navegação deve ser virtual estar em uma classe que pode ser herdada.

Vamos ver isso funcionando no Vs 2017.

Recursos usados

Criando o projeto Console

Abra o VS 2017 Community e crie um novo projeto usando o template .NET Core -> Console App(.NET Core) com o nome EFCore_LazyLoading:

Vamos instalar os seguintes pacotes:

      

   

   

Ao final seu projeto deverá conter as referências aos pacotes acima:

Agora já podemos usar acessar o SQL Server , usar o Migrations e usar os recursos do Lazy Loading no EF Core.

Criando o modelo de domínio e a classe de contexto

Crie uma pasta Models no projeto e a seguir como exemplo vamos criar um modelo de entidades contendo duas classes com uma associação um-para-muitos:

- Autor e Livro onde um autor pode ter muitos livros:

  public class Autor
  {
        public int AutorId { get; set; }
        public string Nome { get; set; }
        public string Email { get; set; }
        public virtual ICollection<Livro> Livros { get; set; }    
  }
  public class Livro
  {
        public int LivroId { get; set; }
        public string Titulo { get; set; }
        public int AnoLancamento { get; set; }
        public virtual Autor Autor { get; set; }
        public int AutorId { get; set; }
  }

Agora vamos criar a classe de contexto chamada ApplicationDBContext :

 public class AppDbContext : DbContext
    {
        public DbSet<Autor> Autores { get; set; }
        public DbSet<Livro> Livros { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                 .UseLazyLoadingProxies()
                 .UseSqlServer("Data Source = MACORATTI; " +
                      "Initial Catalog=CursoEFCOreModulo11DB;Integrated Security=True");
           optionsBuilder.UseLoggerFactory(new LoggerFactory().AddConsole((category, level) =>
                level == LogLevel.Information &&
                   category == DbLoggerCategory.Database.Command.Name, true));
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //------entidade Autor--------------------
            modelBuilder.Entity<Autor>().HasKey(a => a.AutorId);
            modelBuilder.Entity<Autor>()
               .Property(p => p.Nome)
               .HasMaxLength(100)
               .IsRequired();
            modelBuilder.Entity<Autor>()
                .Property(p => p.Email)
                .HasMaxLength(200)
                .IsRequired();
            //------entidade Livro--------------------
            modelBuilder.Entity<Livro>().HasKey(a => a.LivroId);
            modelBuilder.Entity<Livro>()
                .Property(p => p.Titulo)
                .HasMaxLength(200)
                .IsRequired();
            //um-para-muitos :  Livros - Autor
            modelBuilder.Entity<Livro>()
              .HasOne<Autor>(s => s.Autor)
                .WithMany(g => g.Livros)
                   .HasForeignKey(s => s.AutorId);
        }
    }

Esta classe herda de DbContext e define o provedor do banco de dados SqlServer e a string de conexão com o banco de dados.

Define o mapeamento da entidade Autor para a tabela Autores e Livro para Livros e define o relacionamento um-para-muitos entre Autor e Livro usando a Fluent API.

Se o banco de dados e a tabela não existirem podemos criar usando o Migrations.

Criando o banco de dados e a tabela com Migrations

Para criar o banco de dados e a tabela abra o Package Manager Console e digite o comando: Add-Migration MigracaoInicial ou dotnet ef migrations add MigracaoInicial na linha de comando:

Para aplicar a migração e efetivamente criar o banco de dados e a tabela, digite o comando : Update-Database no Package Manager Console ou dotnet ef database update na linha de comando:

Abrindo o SQL Server Management Studio verificamos que o banco de dados CursoEFCoreModulo11DB e as tabela Autores e Livros foram criados com sucesso:

Vamos agora definir o código no arquivo Program.cs para usar o Lazy Loading :

using EFCore_LazyLoading.Models;
using System;
namespace EFCore_LazyLoading
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var contexto = new AppDbContext())
            {
                var resultado = contexto.Autores;
                foreach (var item in resultado)
                {
                    Console.WriteLine($"{item.Nome}");
                    foreach (var l in item.Livros)
                    {
                        Console.WriteLine("\t\t" + l.Titulo);
                    }
                }
            }
            Console.Readkey();
        }
    }
}

Neste código estamos acessando os autores e exibindo o nome de cada autor e a seguir usando a propriedade de navegação Livros exibindo o título dos livros para cada autor.

Como estamos usando o Lazy Loading as propriedades de navegação serão carregadas e veremos no console o seguinte resultado exibindo as consultas SQL Geradas pelo EF Core:

Observe que para cada autor temos uma consulta SQL gerada para obter os livros relacionados.

Conclusão:

O recurso Lazy Loading deve ser usado com cuidado pois pode impactar o desempenho da sua aplicação, principalmente em entidades com associações um-para-muitos, causando o problema conhecido como select n+1 (veja este artigo que trata desse problema).

E por hoje é isso...

"E também todos os que piamente querem viver em Cristo Jesus padecerão perseguições.
Mas os homens maus e enganadores irão de mal para pior, enganando e sendo enganados."
2 Timóteo 3:12,13

 

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti