EF Core - Definindo Relacionamentos usando as convenções
  Neste artigo veremos como definir relacionamentos usando o EF Core de forma simples e direta.


Quando falamos em relacionamentos usando o EF Core isso significa em como a associação entre as entidades vai se refletir no relacionamento entre as tabelas no banco de dados.

 


Os principais tipos de relacionamentos usados no EF Core são:

  1. One-to-One - Um-para-Um

  2. One-to-Many - Um-para-Muitos

  3. Many-to-Many - Muitos-para-Muitos

Os termos usados para definir os relacionamentos são:

O padrão mais comum para relacionamentos é ter propriedades de navegação definidas em ambas as extremidades do relacionamento e uma propriedade de chave estrangeira definida na classe de entidade dependente.

1- Relacionamento One-to-One

 

Para configurar um relacionamento um-para-um, os desenvolvedores podem usar a abordagem da Convenção ou podem até mesmo usar a abordagem da API Fluent.

 

Em teremos de tabelas de banco de dados um relacionamento Um-para-Um ocorre quando há apenas uma linha em uma tabela que está vinculada a apenas uma linha em outra tabela e vice-versa.

 

Os relacionamentos um para um têm uma propriedade de navegação de referência em ambos os lados. Eles seguem as mesmas convenções dos relacionamentos um-para-muitos, mas um índice exclusivo é introduzido na propriedade de chave estrangeira para garantir que apenas um dependente esteja relacionado a cada principal.

 

A propriedade de Navegação em ambas as classes retorna o objeto, e, isso torna difícil para a O EF Core determinar qual classe depende de qual. Portanto, configurar o relacionamento um para um usando a convenção padrão pode não ser tão simples como parece.

 

Para isso definimos na entidade pendente (Endereco) a propriedade de Navegação AlunoId que vai atuar como chave estrangeira.
 

Exemplo:  Aluno e Endereco, onde um aluno pode ter apenas um endereço.

 

1- Aluno

 

public class Aluno
{
    public int Id { get; set; }
    public string? Nome { get; set; }
    public Endereco? Endereco { get; set; }
}

 

2- Endereco

 

public class Endereco
{
    public int Id { get; set; }
    public string? Rua { get; set; }
    public string? Cidade { get; set; }
    public string? Estado { get; set; }
    public int AlunoId { get; set; }
    public Aluno? Aluno { get; set; }
}

 

2- Relacionamento One-to-Many
 

Os relacionamentos um para muitos exigem uma propriedade de navegação de coleção em um dos lados.
 

No banco de dados o relacionamento um-para-muitos é formado quando uma linha da primeira tabela é vinculada a muitas linhas na segunda tabela, mas apenas uma linha da segunda tabela é vinculada a uma linha da primeira tabela.

 

Exemplo:  Blog e Post ,  onde um blog pode ter muitos posts

 

1- Blog
 

public class Blog
{
    public int BlogId { get; set; }
    public string? Url { get; set; }
    public List<Post>? Posts { get; set; }
}

 

2- Post

 

public class Post
{
    public int PostId { get; set; }
    public string? Titulo { get; set; }
    public string? Conteudo { get; set; }
    public Blog? Blog { get; set; }
}

Observe que a propriedade de navegação na classe Post retorna a referência ao objeto de Blog e que a propriedade de navegação na classe Blog retorna a coleção de objetos Post.

Em um relacionamento Um para Muitos, a chave primária da tabela de Blog (BlogId) é definida como a chave estrangeira na tabela Post.

 

Podemos também incluir a propriedade BlogId de forma explicita na classe dependente (Post) :

 

public class Post
{
    public int PostId { get; set; }
    public string? Titulo { get; set; }
    public string? Conteudo { get; set; }
    public int BlogId { get;  set; }
    public Blog? Blog { get; set; }
}

O EF Core vai gerar a propriedde BlogId como uma coluna Not Nullable.  Se você desejar que esta coluna seja Nullable,  defina a propriedade como Nullable conforme mostrado no código abaixo :

public int? BlogId { get;  set; }


2- Relacionamento Many-to-Many


Os relacionamentos um para muitos exigem uma propriedade de navegação de coleção em ambos os lados das entidades.
 

Um relacionamento Muitos-para-Muitos ocorre quando várias linhas de uma tabela são vinculadas a várias linhas de outra tabela e vice-versa.

 

Exemplo: Funcionario e Projeto, onde um funcionário pode fazer parte de mais de um projeto e um projeto pode conter muitos funcionários.

 

1- Funcionario

public class Funcionario
{
    public int FuncionarioId { get; set; }
    public string? Nome { get; set; }    
    public virtual ICollection<Projeto>? Projetos { get; set; }
}

 

2- Projeto

public class Projeto
{
    public int ProjetoId { get; set; }
    public string? Nome { get; set; }
    public float Prazo { get; set; }

    public virtual ICollection<Funcionario>? Funcionarios { get; set; }
}

 

O relacionamento muitos para muitos geralmente envolve a criação de uma tabela de junção.

 

A tabela de junção terá uma chave primária composta que consiste na combinação da chave primária da tabela Funcionarios e da tabela Projetos.

 

Da versão 5.0 do EF Core em diante não precisamos definir uma entidade que vai atuar como a tabela de junção. Isso é feito de forma automatica pelo EF Core. Para o exemplo será criada a tabela de junção FuncionarioProjeto.

 

O uso da palavra-chave virtual apenas vai dar suporte ao Lazy Loading. Para isso basta incluir o pacote Microsoft.EntityFrameworkCore.Proxies e habilitar o recurso definindo UseLazyLoadingProxies.

 

Para os exemplos apresentados, após aplicar a migração, iremos obter o seguinte resultado no banco de dados SQL Server:

 

 

Note que temos a definição dos relacionamentos um-para-um entre Enderecos e Alunos, um-para-muitos entre Blogs e Posts e muitos-para-muitos entre Funcionarios e Projetos.

E usamos apenas as convenções padrão.

Em outro artigo vou mostrar como obter o mesmo resultado usando a Fluent API.

"Nada façais por contenda ou por vanglória, mas por humildade; cada um considere os outros superiores a si mesmo."
Filipenses 2:3

Porque um menino nos nasceu, um filho se nos deu, e o principado está sobre os seus ombros, e se chamará o seu nome: Maravilhoso, Conselheiro, Deus Forte, Pai da Eternidade, Príncipe da Paz.

Isaías 9:6
Porque um menino nos nasceu, um filho se nos deu, e o principado está sobre os seus ombros, e se chamará o seu nome: Maravilhoso, Conselheiro, Deus Forte, Pai da Eternidade, Príncipe da Paz.

Isaías 9:6

Referências:


José Carlos Macoratti