LazyLoad EF Core 2.1(Preview)

18 minuto(s) de leitura - January 27, 2018

01

Fala pessoal, tudo bem?!

Nesse artigo estarei mostrando uma das grandes novidades do Entity Framework Core 2.1, o LazyLoad, (vale lembrar que ainda não foi lançado a versão oficial, mas vocês podem testar com as compilações noturnas, veja nesse link como configurar seu Visual Studio para fazer download dos pacotes em desenvolvimento), antes de tudo vamos entender um pouco sobre o carregamento de dados relacionados, quais são os tipos básicos existentes.
  • Carregamento explícito
  • Carregamento adiantado
  • Carregamento preguiçoso (LazyLoad disponível para o EF Core a partir da Versão 2.1)
Antes de tudo vamos imaginar o seguinte cenário, para que possamos entender melhor o que estaremos explicando aqui neste artigo. Utilizaremos duas classes e um DbContext como exemplo:
(Autor,Livro e ExemploContext)


1 – Primeira Classe chamada Autor, o autor pode ter vários livros.

public class Autor
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public virtual IEnumerable<Livro> Livros {get;set;}
}

2 – Segunda Classe chamada Livro

Essa irá conter um autor (apenas para nosso exemplo ficar mais prático e compreensível, pois sabemos que um livro também pode ter vários autores, sendo assim farei em uma outra oportunidade um artigo sobre N-N (Muitos para muitos).
public class Livro
{
    public int Id { get; set; }
    public string Descricao { get; set; }
    public DateTime DataLancamento { get; set; }

    public int AutorId { get; set; }
    public Autor Autor { get; set; }
}

3 – E Enfim nosso DbContext

public class ExemploContext : DbContext
{
    private const string StringConexao
        = @"Server=.\Sql2016;Database=LazyLoadArtigo;Integrated Security=True;ConnectRetryCount=0";

    public DbSet<Autor> Autores { get; set; }
    public DbSet<Livro> Livros { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // Para habilitar o uso do LazyLoad remova o comentário da linha abaixo
        // optionsBuilder.UseLazyLoadingProxies();
        optionsBuilder.UseSqlServer(StringConexao);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<Livro>()
            .HasOne(p => p.Autor)
            .WithMany(p => p.Livros)
            .HasForeignKey(p => p.AutorId);
    }
}

Classes criadas agora vamos entender os conceitos dos três tipos básicos de carregamento citados acima.

1 - O que é um carregamento explícito?

Basicamente este tipo de carregamento é feito quando existe um relacionamento de dados, e em seu primeiro momento, você carrega apenas as informações principais, e posteriormente de forma manual, forçando a aplicação fazer a leitura do restante das informações que podemos dizer suas “dependências”, vamos a um exemplo prático!


// Buscar um autor
var autor = db
    .Autores
    .FirstOrDefault(p=> p.Id == 1);

Resultado SQL:

SELECT TOP(1) [p].[Id], [p].[Nome]
FROM[Autores] AS[p]
WHERE[p].[Id] = 1

Até aqui os livros não foram carregados ainda, mas para carregar basta executar o procedimento abaixo.
Esse procedimento é chamado de “Carregamento Explícito”, pelo motivo de executarmos ele de forma manual, apenas quando existe a necessidade de preencher uma propriedade de navegação.

// Carregar os livros do autor de forma explícita
db.Entry(autor)
    .Collection(b => b.Livros)
    .Load();

2 - O que é um carregamento adiantado?

Bom particularmente é o que eu mas utilizo, dependendo da quantidade de registros e relacionamentos, é muito mais eficaz utilizar esse tipo de carregamento, você pode ter uma vantagem aqui, que é de ter uma resposta da consulta com tudo já preenchido.
Ou seja, quando o Entity Framework Core irá montar uma query onde retornará os resultados como parte de uma consulta única, efetuando um INNER JOIN com as tabelas que tem relacionamentos, para isso basta fazer o uso do Include, como mostro no exemplo abaixo:


var autorAdiantado = db
    .Autores
    .Include(p=>p.Livros)
    .ToList();
Dessa forma nossa variável autorAdiantado estará totalmente populada com os livros dos respectivos autores, acredito que seja a melhor opção, além de diminuir drasticamente as requisições efetuadas no servidor. Caso tenha mais de um relacionado é só incluir mais Include.


3 - O que é um carregamento preguiçoso?

O carregamento preguiçoso é umas das opções citadas aqui mas utilizada. Sua funcionalidade principal é carregar os valores das propriedades de navegação apenas quando as mesmas forem acessadas, essa funcionalidade é desencadeada internamente quando a propriedade é acessada e seu valor for nulo.

O Entity Framework por sua vez, faz uma requisição no servidor e preenche os dados da propriedade automaticamente, diferente do uso explícito e adiantado.

Até a versão 2.0.1 não era possível a utilização do LazyLoad com Entity Framework Core recentemente isso foi implementado, e estará disponível na versão 2.1 do ORM, esse foi um dos assuntos mais discutidos nos bastidores do projeto.

O carregamento preguiçoso é mas simplificado, bastando apenas efetuar a consulta principal, e as propriedades de navegação automaticamente serão preenchidas no momento que forem acessadas.

Exemplo:

var autorLazyLoad = db.Autores.ToList();

Pronto bem simples, não é?! O restante é por conta do EF Core. A implementação do LazyLoad foi feita em um pacote especifico chamado:

Microsoft.EntityFrameworkCore.Proxies

Para habilitar o uso do LazyLoad no EF Core basta instalar o pacote acima informado e fazer a chamada do método em OnConfiguring no seu DbContext assim:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseLazyLoadingProxies();
    optionsBuilder.UseSqlServer(StringConexao);
}

Você também pode adicionar o LazyLoad como injeção de dependência, no Asp.Net Core basta utilizar o exemplo abaixo:

public void ConfigureServices(IServiceCollection services)
{
    services.AddEntityFrameworkProxies();
}

Observação: para o LazyLoad funcionar, as propriedades de navegação obrigatoriamente devem ser públicas e virtuais.

Vale a pena lembrar que isso é um pacote opcional e não está integrado totalmente ao EF Core, sendo assim é necessário a instalação do mesmo como citado anteriormente no artigo.


Os pacotes instalados para o exemplo deste artigo foram:

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Proxies
  • Microsoft.EntityFrameworkCore.SqlServer

(Compilação noturna – Preview)

01

O projeto de exemplo está no Github acesse aqui!

Abraços e até o próximo!

Deixe um comentário