0Pricing
C# Academy · Aula

Relacionamentos: um para muitos e muitos para muitos

Modele e consulte relacionamentos um para muitos e muitos para muitos com propriedades de navegação e a Fluent API.

Relacionamentos: um para muitos e muitos para muitos é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.

Relacionamentos no EF Core

EF Core modela três tipos de relacionamentos entre entidades: um para um, um para muitos e muitos para muitos. Cada um é expresso com propriedades de navegação e pode ser configurado opcionalmente com a Fluent API.

Um para muitos: configuração da entidade

Um Blog tem muitos Posts. O dependente (Post) contém a chave estrangeira. As propriedades de navegação em ambos os lados permitem percorrer o relacionamento em qualquer direção.

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public ICollection<Post> Posts { get; set; } = new List<Post>();
}

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; } = "";
    public int BlogId { get; set; }        // FK
    public Blog Blog { get; set; } = null!; // nav property
}

Fluent API: um para muitos

EF Core infere o relacionamento por convenção, mas você pode especificá-lo com a Fluent API para obter clareza e definir o comportamento de exclusão em cascata.

protected override void OnModelCreating(ModelBuilder mb)
{
    mb.Entity<Blog>()
      .HasMany(b => b.Posts)
      .WithOne(p => p.Blog)
      .HasForeignKey(p => p.BlogId)
      .OnDelete(DeleteBehavior.Cascade);
}

Consultando com Include (carregamento antecipado)

Use Include para carregar dados relacionados na mesma consulta. Use ThenInclude para avançar na hierarquia de navegação.

// Load blog with all its posts
var blog = await _db.Blogs
    .Include(b => b.Posts)
    .FirstOrDefaultAsync(b => b.Id == 1);

// Load posts with their comments too
var blogs = await _db.Blogs
    .Include(b => b.Posts)
        .ThenInclude(p => p.Comments)
    .ToListAsync();

Muitos para muitos sem entidade de junção

EF Core 5+ oferece suporte a relacionamentos muitos para muitos sem uma entidade de junção explícita. Ele cria a tabela de junção automaticamente usando os nomes dos tipos de entidade.

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public ICollection<Course> Courses { get; set; } = new List<Course>();
}

public class Course
{
    public int Id { get; set; }
    public string Title { get; set; } = "";
    public ICollection<Student> Students { get; set; } = new List<Student>();
}
// EF creates StudentCourse join table automatically

Muitos para muitos com entidade de junção

Quando a tabela de junção precisa de colunas adicionais (por exemplo, data de matrícula e nota), crie uma entidade de junção explícita com uma chave primária composta.

public class Enrollment
{
    public int StudentId { get; set; }
    public Student Student { get; set; } = null!;
    public int CourseId { get; set; }
    public Course Course { get; set; } = null!;
    public DateTime EnrolledAt { get; set; }
    public decimal? Grade { get; set; }
}

// Fluent API config:
mb.Entity<Enrollment>().HasKey(e => new { e.StudentId, e.CourseId });
mb.Entity<Enrollment>().HasOne(e => e.Student).WithMany(s => s.Enrollments);
mb.Entity<Enrollment>().HasOne(e => e.Course).WithMany(c => c.Enrollments);

Inserindo dados relacionados

Adicione entidades relacionadas à coleção do pai antes de chamar SaveChangesAsync. EF Core lida automaticamente com os valores de FK.

var blog = new Blog { Name = "Dev Notes" };
blog.Posts.Add(new Post { Title = "Hello EF Core" });
blog.Posts.Add(new Post { Title = "Migrations Deep Dive" });

_db.Blogs.Add(blog);
await _db.SaveChangesAsync();
// Inserts Blog + 2 Posts with correct BlogId FK

Filtrando dados relacionados

Você pode filtrar propriedades de navegação em LINQ. EF Core traduz essas expressões automaticamente em operações JOIN no SQL.

// Blogs that have at least one published post
var popularBlogs = await _db.Blogs
    .Where(b => b.Posts.Any(p => p.IsPublished))
    .Select(b => new { b.Name, PostCount = b.Posts.Count(p => p.IsPublished) })
    .OrderByDescending(b => b.PostCount)
    .ToListAsync();

Exclusão em cascata

Com DeleteBehavior.Cascade, excluir a entidade principal (Blog) exclui automaticamente todas as entidades dependentes (Post). Outras opções: SetNull, Restrict, NoAction.

// Delete a blog and all its posts
var blog = await _db.Blogs.FindAsync(1);
_db.Blogs.Remove(blog!);
await _db.SaveChangesAsync();
// Cascade: all Posts with BlogId=1 are also deleted

Entidades pertencentes para objetos de valor

Os tipos de entidade pertencentes são excelentes para objetos de valor (por exemplo, Address). Eles são armazenados na mesma tabela que o proprietário e não têm uma identidade independente.

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public Address ShippingAddress { get; set; } = new();
}

public class Address
{
    public string Street { get; set; } = "";
    public string City { get; set; } = "";
    public string Country { get; set; } = "";
}

// Fluent API:
mb.Entity<Customer>().OwnsOne(c => c.ShippingAddress);

Na prática: pedido com itens de linha

Um padrão completo de comércio eletrônico: Order (principal) com muitos OrderLines (dependentes), cada um referenciando um Product.

var order = await _db.Orders
    .Include(o => o.Lines)
        .ThenInclude(l => l.Product)
    .FirstOrDefaultAsync(o => o.Id == orderId);

if (order is null) return Results.NotFound();

var summary = new
{
    OrderId = order.Id,
    Total   = order.Lines.Sum(l => l.Quantity * l.Product.Price),
    Items   = order.Lines.Select(l => new
    {
        l.Product.Name,
        l.Quantity,
        LineTotal = l.Quantity * l.Product.Price
    })
};
return Results.Ok(summary);

Verificação rápida

Quando EF Core cria automaticamente uma tabela de junção sem uma entidade de junção explícita?

Revisão: relacionamentos no EF Core

Principais conclusões:

  • Um para muitos: FK no dependente; navegação em ambos os lados; use Include para carregar
  • Muitos para muitos (simples): duas navegações ICollection — EF Core cria automaticamente a tabela de junção
  • Muitos para muitos (com dados adicionais): entidade de junção explícita com PK composta
  • A exclusão em cascata controla o que acontece aos dependentes quando a entidade principal é removida
  • Entidades pertencentes modelam objetos de valor na mesma tabela que o proprietário

Perguntas Frequentes

A aula “Relacionamentos: um para muitos e muitos para muitos” é grátis?

Sim — o texto completo de “Relacionamentos: um para muitos e muitos para muitos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.

O que vou aprender em “Relacionamentos: um para muitos e muitos para muitos”?

Modele e consulte relacionamentos um para muitos e muitos para muitos com propriedades de navegação e a Fluent API. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C# Academy?

Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Relacionamentos: um para muitos e muitos para muitos”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C# Academy?

Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Fundamentos de DbContext e DbSet
  2. Migrações e gerenciamento de esquema
  3. Operações CRUD com EF Core
  4. Relacionamentos: um para muitos e muitos para muitos
← Voltar para C# Academy