Modelos C# y relaciones con Entity Framework
Clase 14 de 21 • Curso de APIs con .NET
Contenido del curso
Estructura de una Web API
- 7

Configuración CORS en .NET: solución al error
07:08 min - 8

Rutas en APIs .NET con parámetros
12:50 min - 9

Documentación de APIs con OpenAPI y Swagger en .NET
14:25 min - 10

Middlewares en ASP.NET: pipeline y custom middleware
10:32 min - 11

Inyección de dependencias en .NET: ILogger
09:18 min - 12

Middleware para autenticación básica en .NET
08:17 min
Arquitectura y Middlewares
- 13

Configuración de Entity Framework Core en .NET
07:31 min - 14

Modelos C# y relaciones con Entity Framework
Viendo ahora - 15

Servicios con Entity Framework para ASP.NET
13:51 min - 16

Cómo crear controladores API en .NET
14:47 min - 17

Conectar API .NET con PostgreSQL
06:57 min - 18

Conectar API .NET a PostgreSQL con EF Core
06:57 min - 19

Clean Architecture en .NET APIs escalables
09:08 min - 20

Pruebas unitarias con xUnit, InMemory y Copilot
09:05 min - 21

Qué sigue después de tu API con .NET
02:16 min
Aprende a definir modelos C# que se convierten en tablas con Entity Framework y su Fluent API, creando una relación clara entre usuarios y tareas para una API. Verás cómo evitar avisos de nulos, configurar restricciones como longitud y requeridos, y declarar claves y relaciones para consultar datos de forma eficiente.
¿Cómo crear los modelos y propiedades base?
Comienza creando la carpeta models y dos clases: User.cs y TaskItem. La meta es crear tareas y asignar un usuario a cada una.
¿Qué carpeta y archivos se crean?
- Carpeta: models.
- Archivo: User.cs para el usuario.
- Archivo: TaskItem para la tarea.
¿Qué propiedades definen User y TaskItem?
- En User: ID (int), name (string) con valor por defecto, email (string) con valor por defecto. Se recomienda agregar datos como dirección o teléfono si aporta al dominio.
- En TaskItem: ID, title (string) con valor por defecto, isCompleted (bool), userID (int) como clave foránea y la navegación user (permitiendo nulos) para obtener los datos del usuario asignado.
Ejemplo base en C#:
public class User
{
public int ID { get; set; }
public string Name { get; set; } = ""; // valor por defecto para evitar null warnings
public string Email { get; set; } = ""; // valor por defecto
// Propiedad de navegación para las tareas asignadas al usuario
public ICollection<TaskItem> Tasks { get; set; } = new List<TaskItem>();
}
public class TaskItem
{
public int ID { get; set; }
public string Title { get; set; } = ""; // valor por defecto
public bool IsCompleted { get; set; }
public int UserID { get; set; } // clave foránea hacia User
public User? User { get; set; } // navegación opcional
}
¿Cómo configurar Entity Framework con Fluent API?
En AppDbContext agrega los DbSet y sobrescribe OnModelCreating para controlar nombres de tabla, claves, requeridos, longitudes y valores por defecto. Esta configuración en Fluent API hace explícita la estructura que tendrá la base de datos.
¿Cómo exponer las colecciones con DbSet?
- Agrega
DbSet<User>como users (plural) yDbSet<TaskItem>como task (simplificado). Cada DbSet se convierte en una tabla.
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<TaskItem> Task { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// User
modelBuilder.Entity<User>(entity =>
{
entity.ToTable("users");
entity.HasKey(u => u.ID);
entity.Property(u => u.Name)
.IsRequired()
.HasMaxLength(100);
entity.Property(u => u.Email)
.IsRequired()
.HasMaxLength(200);
});
// TaskItem
modelBuilder.Entity<TaskItem>(entity =>
{
entity.ToTable("task");
entity.HasKey(t => t.ID);
entity.Property(t => t.IsCompleted)
.HasDefaultValue(false); // por defecto, no completada
entity.HasOne(t => t.User)
.WithMany(u => u.Tasks)
.HasForeignKey(t => t.UserID);
});
}
}
¿Qué ventajas aporta Fluent API en este contexto?
- Define ToTable para nombres consistentes de tablas.
- Establece HasKey para la clave primaria.
- Marca propiedades IsRequired y HasMaxLength para control de datos.
- Fija HasDefaultValue para comportamientos iniciales seguros.
- Hace explícitas las relaciones y claves foráneas.
¿Qué relación usuario-tarea se implementa y cómo navegar?
La relación es uno a muchos: un usuario puede tener muchas tareas. En TaskItem se declara UserID como clave foránea y la navegación User. En User, una colección ICollection<TaskItem> permite acceder a las tareas asignadas.
¿Por qué usar propiedades de navegación?
- Para consultar una tarea junto con su usuario en una sola operación.
- Para recorrer desde el usuario a sus tareas sin escribir joins manuales.
- Para inicializar la colección y evitar nulos en listas al instanciar entidades.
Acciones clave que quedaron claras: - Crear modelos y establecer valores por defecto para evitar nulos. - Configurar con Fluent API nombres de tablas, claves y restricciones. - Definir HasOne/WithMany y ForeignKey para la integridad referencial. - Inicializar la lista de tareas del usuario para evitar errores al acceder.
Reto práctico: agrega al modelo de User la propiedad role y configura su longitud y requerido con Fluent API. ¿Qué reglas pondrías y por qué?
¿Tienes dudas o quieres compartir tu avance? Comenta qué restricciones añadirías a name, email o role y cómo validarías isCompleted y title en tu escenario.