EF Core 5 — Relacionamento Muitos para Muitos
O Entity Framework Core 5 implementou a relação que faltava entre entidades de forma muito simples e de fácil entendimento. É a muitos para muitos (N x N), onde situações de múltiplos dados entre duas tabelas ocorrem diversas vezes.
Vamos a um projeto prático de Console Application (NET 5.0) contendo os seguintes pacotes instalados:
<PackageReference Include=”Microsoft.EntityFrameworkCore” Version=”5.0.4" />
<PackageReference Include=”Microsoft.EntityFrameworkCore.SqlServer” Version=”5.0.4" />
<PackageReference Include=”Microsoft.EntityFrameworkCore.Tools” Version=”5.0.4">
Modelo de classe
Crie uma nova classe conforme o código a seguir, contendo as classes Curso e Aluno. Em Curso, temos a chave primária CursoId, o Título, CargaHoraria e a propriedade Alunos, que é uma coleção de alunos.
Na Alunos temos a chave primária AlunoId, Nome do alunos e Cursos, que é uma coleção de Curso do respectivo aluno.
Cabe ressaltar que no EF se você declarar a propriedade com o mesmo nome da classe + ID, automaticamente esta propriedade será a chave primária, dispensando de ter que declarar com o [Key].
Sendo assim, teremos um aluno com vários cursos e um curso com vários alunos.
Em seguida, crie o contexto chamado BancoContexto que herda de DbContext contendo os dois DbSets para fazer o CRUD dinamicamente de Cursos e Alunos.
Em OnConfiguring, declare a string de conexão do banco SQL Server, seguido do comando para habilitar o LOG de Command, assim podemos checar quando executarmos o projeto, quais as instruções T-SQL foram solicitadas no banco.
Para aprender a usar o LOG, leia este artigo:
Agora é preciso definir no OnModelCreating o tipo de relação entre as classes, afim de que o EF Core 5 crie a tabela de ligação no banco de dados.
Note como é feita a declaração da classe Aluno que tem muitos (HasMany) Cursos de muitos (WithMany) Alunos. Agora que vem o grande momento de informar qual será a tabela de ligação, neste caso, UsingEntity ToTable(“AlunoCurso”). Ou seja, será criada somente no banco de dados uma terceira tabela de ligação chamada AlunoCurso, contendo as respectivas chaves primárias.
O restante do código é para inserir registros de exemplos, já que usarei o Migrations para criar o banco e as tabelas.
Compile o projeto, verifique se há algum erro e corrija, o importante é chegar até aqui compilado com sucesso.
Migrations
Como temos as duas classes e o contexto, abra o Package Manager Console e digite os comandos a seguir para criar a classe C# e o banco de dados.
PM> Add-Migration SetupInicial
PM> Update-Database
Neste código gerado pelo Tools do EF Core mostra os 3 CreateTable com as respectivas estruturas, campos e propriedades a serem criadas no banco de dados.
Pra mostrar visualmente o tipo de relação criada entre as tabelas no SQL Server, veja a imagem a seguir. Cabe ressaltar que no EF Core 5, o uso do UsingEntity ToTable(“AlunoCurso”) é o segredo para estabelecer as relações muito para muitos.
Program
Vamos a um exemplo prático de como inserir e ler todos os dados destas tabelas. Abra o Program.cs e digite o código a seguir para primeiro inserir alguns registros.
Pressione F5 para executar o projeto e veja o resultado do LOG com o DbCommand do ExecuteReader, as declarações dos parâmetros, os T-SQL gerados para Select e Insert. Com este LOG você sabe o que foi exatamente executado no banco. Pronto, registros inseridos com sucesso.
Agora vamos listar todos os registros. No Program.cs, comente a linha do método que adiciona registros e digite o método que lê todos os cursos e todos os alunos do respectivo curso. Usei dois foreach aninhados, sendo que no primeiro temos a declaração do INCLUDE de alunos para entidade cursos. Isto é necessário porque precisamos ler todos os alunos (a => a.Alunos) da classe cursos (ctx.Cursos), neste caso, a.Alunos é a propriedade da classe Cursos que contém uma coleção de alunos.
Execute o projeto e veja o resultado do LOG para entender e visualizar o comando executado T-SQL Select + LEFT JOIN, assim como o resultado do foreach.
Conclusão
Aplique o modelo usado neste artigo para que você tire proveito deste recursos nos seus projetos. Caso vcoê já tenha um baco de dados criado, pode fazer engenharia reversa usando o EF Core Power Tools (extensão do VS) e aplicar exatamente o relacionamento muitos para muitos, deixando o código mais fácil de entender e aplicar.
E, sempre procure estudar e compartilhar o conhecimento, não tenha dúvida que sempre haverá um desenvolvedor pesquisando por tal solução. Bons estudos e sucesso nos projetos.
Repositório do código fonte:
rehaddad/EFCore5MuitosParaMuitos (github.com)
Renato Haddad
Microsoft Most Valuable Professional
rehaddad@msn.com