Sobes.tech
Middle

Como implementar uma relação muitos-para-muitos em C#?

sobes.tech IA

Resposta da IA

A relação de "muitos para muitos" em C# usando Entity Framework Core geralmente é implementada através de uma tabela intermédia (de ligação).

Etapas de implementação:

  1. Criar entidades: Defina duas classes de entidades para ambos os lados da relação.
  2. Criar uma entidade intermédia: Crie uma classe de entidade separada para a tabela intermédia. Esta entidade conterá chaves estrangeiras para ambas as entidades relacionadas e, opcionalmente, propriedades adicionais que descrevem a própria relação.
  3. Configurar relações no DbContext: No método OnModelCreating do seu DbContext, configure as relações entre a entidade intermédia e as duas entidades principais. Use os métodos HasMany, WithMany, UsingEntity para configurar explicitamente a tabela intermédia.

Exemplo:

Suponha que você tenha as entidades Book e Author, e que um livro possa ser escrito por vários autores, e um autor possa escrever vários livros.

// Entidade 1
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ICollection<BookAuthor> BookAuthors { get; set; }
}

// Entidade 2
public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<BookAuthor> BookAuthors { get; set; }
}

// Entidade intermédia
public class BookAuthor
{
    public int BookId { get; set; }
    public Book Book { get; set; }

    public int AuthorId { get; set; }
    public Author Author { get; set; }

    // Propriedades adicionais, por exemplo, o papel do autor no livro
    public string Role { get; set; }
}
// Configuração no DbContext
public class ApplicationDbContext : DbContext
{
    public DbSet<Book> Books { get; set; }
    public DbSet<Author> Authors { get; set; }
    public DbSet<BookAuthor> BookAuthors { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BookAuthor>()
            .HasKey(ba => new { ba.BookId, ba.AuthorId }); // Chave primária composta

        modelBuilder.Entity<BookAuthor>()
            .HasOne(ba => ba.Book)
            .WithMany(b => b.BookAuthors)
            .HasForeignKey(ba => ba.BookId);

        modelBuilder.Entity<BookAuthor>()
            .HasOne(ba => ba.Author)
            .WithMany(a => a.BookAuthors)
            .HasForeignKey(ba => ba.AuthorId);
    }
}

Utilização:

// Adicionando um livro e um autor
var book = new Book { Title = "Meu Livro Incrível" };
var author = new Author { Name = "Jane Doe" };

var bookAuthor = new BookAuthor {
    Book = book,
    Author = author,
    Role = "Autor Principal"
};

_context.Books.Add(book);
_context.Authors.Add(author);
_context.BookAuthors.Add(bookAuthor);

_context.SaveChanges();

// Obtendo o livro com autores
var bookWithAuthors = _context.Books
    .Include(b => b.BookAuthors)
    .ThenInclude(ba => ba.Author)
    .FirstOrDefault(b => b.Id == book.Id);

// Obtendo o autor com livros
var authorWithBooks = _context.Authors
    .Include(a => a.BookAuthors)
    .ThenInclude(ba => ba.Book)
    .FirstOrDefault(a => a.Id == author.Id);

Esta abordagem com uma entidade intermediária é recomendada no EF Core, pois permite gerenciar de forma flexível dados adicionais sobre a relação. Em casos mais simples, o EF Core pode criar automaticamente uma tabela intermediária oculta, mas definir explicitamente a entidade oferece maior controle.