Olá pessoal,
Depois um longo tempo sem escrever sobre o EntityFramework, vou retomar com uma série de artigos sobre esta nova versão, o EntityFramework Core.
Para quem ainda não sabe, o EF Core faz parte do .NET Core, que é multi plataforma.
Primeiro, vamos precisamos entender que o EF Core é um ORM totalmente novo, criado literalmente do ZERO, e por isto, ainda tem muitas coisas para serem feitas! Lembrando ainda que o EntityFramework 6 continua existindo como parte do .NET Full Framework.
No EF Core, com o lançamento da versão 2.1, tivemos uma boa evolução da ferramenta, e também a implementação do Lazy Loading.
Mas o que é o Lazy Loading ?
Quando temos relacionamentos no nosso modelo de dados, por exemplo, um Cliente com Pedidos, o EF nos permite que, ao ler o cliente, os pedidos possam ser trazidos também.
Mas isto pode deixar tudo muito lento, pois podemos ter vários clientes, com vários pedidos, e os pedidos também tem outros relacionamentos, como produtos, vendedores, etc.
Para a carga dos dados ficar mais rápida, o Lazy Loading, ou carga atrasada, é empregado e os dados relacionados são trazidos somente se eles forem consultados, ou acionados.
Para demonstrar isto na prática, vamos criar um projeto novo no Visual Studio Code do tipo console, e para tornar isto ainda mais divertido, vamos fazer tudo na linha de comandos:
dotnet new console
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
Estes comandos vão criar um projeto .NET Core console e adicionar o EF Core e o provider do SQL Server.
Vou utilizar para este exemplo o banco de dados NorthWind (vou colocar o script no Git)
Agora que temos o projeto, vamos criar duas classes: Customers e Orders (Se preferir, pode fazer engenharia reversa usando este outro artigo):
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace LazyLoading
{
public class Customers
{
[Key]
public string CustomerID {get; set;}
public string CompanyName {get; set;}
public string ContactName {get; set;}
public virtual ICollection<Orders> Orders {get; set;}
public Customers()
{
Orders = new List<Orders>();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace LazyLoading
{
public class Orders
{
[Key]
public int OrderID {get; set;}
public string CustomerID {get; set;}
public virtual Customers Customers {get; set;}
public DateTime OrderDate {get; set;}
}
}
Neste exemplo não estou utilizando todos os campos das tabelas, pois isto não irá interferir.
E por fim a nossa classe de contexto:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.SqlServer;
namespace LazyLoading
{
public class Contexto : DbContext
{
public DbSet<Customers> Customers {get; set;}
public DbSet<Orders> Orders {get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var conexao = new SqlConnectionStringBuilder()
{
DataSource = "(local)",
InitialCatalog = "NorthWind",
IntegratedSecurity = true
};
optionsBuilder.UseSqlServer(conexao.ConnectionString);
}
}
}
Bom, até agora nada de diferente, certo ? Vamos então listar os dados:
using System;
namespace LazyLoading
{
class Program
{
static void Main(string[] args)
{
var db = new Contexto();
var cliente = db.Customers;
foreach(var c in cliente)
{
Console.WriteLine($"{c.CompanyName} - Orders: {c.Orders.Count}");
}
}
}
}
E o resultado da execução:
Veja que todos os clientes possuem ZERO Orders, isto porque o LazyLoading está desativado ainda!
Vamos então habilitar o LazyLoading adicionando um novo pacote ao nosso projeto:
dotnet add package Microsoft.EntityFrameworkCore.Proxies
Agora podemos habilitar no nosso contexto com o seguinte código na classe Contexto.cs:
using Microsoft.EntityFrameworkCore.Proxies;
e adicionando o comando:
optionsBuilder.UseLazyLoadingProxies();
Nossa classe ficará assim:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.SqlServer;
using Microsoft.EntityFrameworkCore.Proxies;
namespace LazyLoading
{
public class Contexto : DbContext
{
public DbSet<Customers> Customers {get; set;}
public DbSet<Orders> Orders {get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var conexao = new SqlConnectionStringBuilder()
{
DataSource = "(local)",
InitialCatalog = "NorthWind",
IntegratedSecurity = true
};
optionsBuilder.UseSqlServer(conexao.ConnectionString);
optionsBuilder.UseLazyLoadingProxies();
}
}
}
Pronto, agora vamos executar novamente e teremos as Ordens:
Se compararmos com o EntityFramework 6, ficou um pouco diferente, pois temos opção somente para LazyLoading e Proxy, o que eu não acho particularmente muito interessante, já que o objeto resultante vem com o proxy, veja:
Isto acontece porque a Microsoft utilizou o Castle Proxy para implementar o LazyLoading, algo que será melhorado em versões posteriores.
O código fonte deste projeto esta mo meu GitHub em: https://github.com/carloscds/EFCoreSamples
Abraços e até a próxima!
Carlos dos Santos.