0Pricing
C# Academy · Lección

Relaciones: One-to-Many y Many-to-Many

Modele y consulte relaciones one-to-many y many-to-many con propiedades de navegación y Fluent API.

Relaciones: One-to-Many y Many-to-Many es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.

Relaciones en EF Core

EF Core modela tres tipos de relaciones entre entidades: uno a uno, uno a varios y varios a varios. Cada una se expresa mediante propiedades de navegación y, opcionalmente, se configura con la API Fluent.

Uno a varios: configuración de las entidades

Un Blog tiene muchos Posts. El dependiente (Post) contiene la clave foránea. Las propiedades de navegación de ambos lados permiten recorrer la relación en cualquier dirección.

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
}

API Fluent: uno a varios

EF Core deduce la relación por convención, pero puede especificarla mediante la API Fluent para aportar claridad y establecer el comportamiento de eliminación en cascada.

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

Consultar con Include (carga anticipada)

Use Include para cargar los datos relacionados en la misma consulta. Use ThenInclude para profundizar en el grafo de navegación.

// 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();

Varios a varios sin una entidad de unión

EF Core 5+ admite relaciones de varios a varios sin una entidad de unión explícita. Crea automáticamente la tabla de unión utilizando los nombres de los tipos de entidad.

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

Varios a varios con una entidad de unión

Cuando la tabla de unión necesita columnas adicionales (por ejemplo, la fecha de inscripción o la calificación), cree una entidad de unión explícita con una clave principal compuesta.

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);

Insertar datos relacionados

Agregue las entidades relacionadas a la colección del elemento principal antes de llamar a SaveChangesAsync. EF Core gestiona automáticamente los valores de las claves foráneas.

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

Filtrar datos relacionados

Puede filtrar las propiedades de navegación en LINQ. EF Core las traduce automáticamente a JOIN de 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();

Eliminación en cascada

Con DeleteBehavior.Cascade, al eliminar el elemento principal (Blog) se eliminan automáticamente todos los elementos dependientes (Posts). Otras opciones: 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 propias para objetos de valor

Los tipos de entidad propia son ideales para objetos de valor (por ejemplo, Address). Se almacenan en la misma tabla que el propietario y no tienen una identidad independiente.

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);

En la práctica: pedido con líneas de pedido

Un patrón completo de comercio electrónico: Order (elemento principal) con muchos OrderLines (elementos dependientes), cada uno de los cuales hace referencia a un 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);

Comprobación rápida

¿Cuándo crea EF Core automáticamente una tabla de unión sin una entidad de unión explícita?

Repaso: relaciones en EF Core

Conceptos clave:

  • Uno a varios: la clave foránea está en el dependiente; hay navegación en ambos lados; use Include para cargar los datos
  • Varios a varios (simple): dos navegaciones ICollection; EF Core crea automáticamente la tabla de unión
  • Varios a varios (con datos adicionales): entidad de unión explícita con una clave principal compuesta
  • La eliminación en cascada controla qué sucede con los dependientes cuando se elimina el elemento principal
  • Las entidades propias modelan objetos de valor en la misma tabla que el propietario

Preguntas frecuentes

¿La lección «Relaciones: One-to-Many y Many-to-Many» es gratis?

Sí — el texto completo de «Relaciones: One-to-Many y Many-to-Many» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Relaciones: One-to-Many y Many-to-Many»?

Modele y consulte relaciones one-to-many y many-to-many con propiedades de navegación y Fluent API. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C# Academy?

No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Relaciones: One-to-Many y Many-to-Many»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C# Academy?

Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Fundamentos de DbContext y DbSet
  2. Migraciones y gestión del esquema
  3. Operaciones CRUD con EF Core
  4. Relaciones: One-to-Many y Many-to-Many
← Volver a C# Academy