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#