EF Core 2.0 - Novos Recursos : Table Splitting e Owned Types
Neste artigo vou apresentar dois novos recursos do Entity Framework Core 2.0 chamados table splitting e owned types. |
Em muitos cenários onde estamos usando uma ferramenta ORM como o Entity FrameworkCore ocorre que a classe da entidade pode definir propriedades complexas, como por exemplo, uma classe Cliente que possui uma propriedade Resindencial do tipo Endereço, e a propriedade Endereço esta definida como uma propriedade de navegação na classe Cliente quando o mapeamento da tabela do banco de dados for definido.
Nota: Esse artigo foi baseado no original: http://www.dotnetcurry.com/entityframework/1398/efcore-2-new-features com ajustes e adaptações.
Na versão do EF Core 2.0, temos disponível agora os recursos Table Splitting e Own Type que são usados para gerenciar a geração e o mapeamento da tabela do banco de dados.
Table Splitting
No EF Core 2.0 agora é possível mapear dois ou mais tipos de entidade para a mesma tabela. Sendo que a coluna da chave primária será compartilhada e cada linha irá corresponder a todas as entidades mapeadas.
Na table splitting , o a chave de relacionamento deve ser configurada em todos os tipos de entidades para essas tabelas compartilhadas.
Owned Types
Neste recurso, a entidade proprietária pode compartilhar o mesmo tipo CLR com
outro tipo de entidade proprietária.
Para isso deve haver um conjunto de navegação para o outro tipo de entidade pois
o tipo de propriedade não pode ser identificado apenas pelo tipo CLR.
Assim, a entidade que contém a definição da navegação é a proprietária e quando o proprietário for consultado os tipos de propriedade serão incluídos por padrão.
Vamos ver
como isso funciona na prática..
Recursos usados:
Criando a solução e o projeto no VS Community
Abra o VS 2017 Community e crie uma solução em branco escolhendo : Other Project Types-> Visual Studio Solutions e clicando em Blank Solution;
Informe o nome EFCore2_TableSplitting e clique em OK;
No menu File clique em Add Project e escolha .NET Core e o template Console App (.NET Core) informando o nome Exemplo_Normal:
Agora vamos incluir as seguintes referências via Nuget em nosso projeto:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Console
No menu Tools clique em Nuget Package Manager e a seguir em Manage Nuget Packages for Solution;
Clique em Browse e localize o pacote e a seguir marque o projeto e clique em Install.
Repita o procedimento acima para cada pacote.
Criando o modelo de entidades
Crie uma pasta chamada Models no projeto e a seguir crie as classes : Cliente, Endereco, Regiao e Pais conforme o código mostrado a seguir:
1- Cliente
public class Cliente
{
public int ClienteId { get; set; }
public string Nome { get; set; }
public string Email { get; set; }
public Endereco Comercial { get; set; }
public Endereco Residencial { get; set; }
}
|
2- Endereco
public class Endereco
{
public string Localizacao { get; set; }
public string Complemento { get; set; }
public string CodigoPostal { get; set; }
public Regiao Regiao { get; set; }
}
|
3- Regiao
public class Regiao
{
public int RegiaoId { get; set; }
public string Cidade { get; set; }
public string Estado { get; set; }
public string PaisId { get; set; }
public Pais Pais { get; set; }
}
|
4- Pais
[Table("Paises")
public class Pais
{
public string PaisId { get; set; }
public string PaisNome { get; set; }
}
|
Resumindo temos o seguinte :
A classe Regiao contém a propriedade PaisId do tipo string e a propriedade Pais do tipo Pais.
A classe Endereco contém a propriedade Regiao do tipo Regiao.
A classe Cliente define as propriedades Residencial e Comercial do tipo Endereco.
Com base neste código teremos a criação de 3 tabelas : Paises, Regioes e Clientes
Para ter certeza de que Cliente possui o tipo Endereco e, desde que o Endereco contém Regiao como uma propriedade, precisamos dividir o mapeamento nas tabelas Pessoa e Regiao.
Vamos definir isso na classe de contexto que iremos criar a seguir.
Na pasta Models crie a classe de contexto chamada ClienteDbContext que herda de DbContext e onde vamos definir o mapeamento:
5- ClienteDbContext
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace Exemplo_Normal.Models
{
public class ClienteDbContext : DbContext
{
public DbSet<Cliente> Clientes { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(@"Data Source=MACORATTI;Initial Catalog=ClienteDB;Integrated Security=True")
.UseLoggerFactory(new LoggerFactory().AddConsole());
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//A tabela Cliente vai ter o endereço residencial e sua propriedade
modelBuilder.Entity<Cliente>()
.OwnsOne(p => p.Residencial)
.OwnsOne(r => r.Regiao);
//O Table Splitting, vai gerar duas tabelas: Clientes e Regioes
modelBuilder.Entity<Cliente>()
.OwnsOne(p => p.Comercial)
.ToTable("Regioes").
OwnsOne(r => r.Regiao);
}
}
}
|
Nesta classe ClienteDbContext definimos a propriedade Clientes do tipo DbSet que vai mapear a entidade Cliente para a tabela Clientes.
No método OnModelCreating temos o código onde o método OwnsOne é usado duas vezes :
modelBuilder.Entity<Cliente>()
.OwnsOne(c => c.Residencial)
.OwnsOne(r =>
r.Regiao);
Na primeira chamada temos que a entidade Cliente possui a propriedade Residencial do tipo Endereco visto que esta propriedade esta definida na entidade Cliente.
A classe Endereco define a propriedade Regiao do tipo Regiao e a próxima chamada a OwnsOne indica que a propriedade Regiao pertence à classe Endereco.
modelBuilder.Entity<Cliente>()
.OwnsOne(p => p.Comercial)
.ToTable("Regioes").
OwnsOne(r => r.Regiao);
Neste código acima a propriedade Comercial pertence à classe Cliente e o método ToTable() aceita um string indicando o nome da tabela 'Regioes' que será mapeada com a entidade.
Definindo o código do método Main da classe Program
Vamos agora definir o código no método Main() da classe Program onde vamos criar o banco de dados e as tabelas, incluir alguns dados e realizar o Table Splitting e usar o Owned Type.
Abaixo vemos o código incluido no método Main():
using Exemplo_Normal.Models; using Microsoft.EntityFrameworkCore; using System; using static System.Console;
namespace Exemplo_Normal //cria uma instância do contexto //define um pais //cria um cliente com endereco, regiao e pais //inclui o cliente e persiste no banco de dados //obtém a relação de clientes //percorre cada cliente e exibe as informações static void GerenciaBancoDados() |
Neste código iniciamos chamando o método GerenciaBancoDados que garante que o banco de dados será criado sempre que executarmos o código.
O restante do código já esta comentado.
Executando o projeto iremos obter o seguinte resultado:
Nota: A figura acima mostra a penas o resultado exibindo as informações de cliente, endereço e região.
Se abrirmos o SQL Server Management Studio iremos ver as tabelas : Clientes, Paises e Regioes criadas com a seguinte estrutura:
Assim temos:
Aqui vemos os recursos Owned Type e Table Splitting fornecendo um mecanismo para gerenciar a navegação para definir a Entidade Proprietária e mapeando a entidade para mais de uma tabela.
Note que na classe ClienteDbContext definimos apenas uma propriedade DbSet<Cliente>, mas o banco de dados foi criado com 3 tabelas.
Pegue o projeto completo aqui : EFCore2_TableSplitting.zip
Eu sou a videira
verdadeira, e meu Pai é o lavrador.
Toda a vara em mim, que não dá fruto, a tira; e limpa toda aquela que dá fruto,
para que dê mais fruto.
João 15:1,2
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#