🚀 Introducción
Como desarrollador e instructor técnico con experiencia en backend y frontend, he visto que muchos proyectos fallan no por falta de código, sino por un mal modelado de datos. En 2025, donde la escalabilidad y el rendimiento son esenciales, dominar el modelado de datos en .NET 9 con Entity Framework Core es una habilidad clave para cualquier desarrollador que busque crear soluciones profesionales.
En esta guía práctica aprenderás, paso a paso, cómo crear un proyecto completo con modelado de datos, desde el diseño conceptual hasta la implementación en código. Además, compartiré ejemplos reales y errores comunes basados en mi experiencia en proyectos de producción.
🔍 ¿Qué es el modelado de datos?
El modelado de datos es el proceso de diseñar la estructura lógica y física de una base de datos. Define cómo se almacenan, relacionan y consultan los datos dentro de una aplicación.
En el contexto de .NET 9 y Entity Framework Core (EF Core 9), el modelado se realiza a través de clases C# que representan las entidades del negocio, y sus relaciones se configuran mediante Data Annotations o Fluent API.
Ejemplo básico de modelo:
public class Product
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; } = string.Empty;
[Precision(10, 2)]
public decimal Price { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; } = null!;
}
🌐 ¿Por qué es importante en 2025?
En 2025, los sistemas modernos deben ser rápidos, escalables y seguros. Un modelado de datos correcto:
- Evita redundancia y errores de consistencia.
- Mejora el rendimiento de consultas.
- Facilita la evolución del proyecto (versionado, migraciones y nuevas funcionalidades).
- Optimiza el consumo en la nube, ya que estructuras bien diseñadas reducen costos de almacenamiento y procesamiento en plataformas como Azure o AWS.
Además, con las mejoras introducidas en EF Core 9, podemos aprovechar mapeo jerárquico, tipos complejos y relaciones polimórficas, lo que permite un modelado más natural y flexible.
🧩 Paso a paso: Proyecto completo con modelado de datos en .NET 9
🧱 1. Crear el proyecto base
Abre tu terminal y ejecuta:
dotnet new webapi -n DataModelingDemo
cd DataModelingDemo
Instalamos Entity Framework Core y el proveedor SQL Server:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
🧩 2. Crear las entidades del dominio
Supongamos que estamos desarrollando un sistema de ventas con las entidades principales:Product, Category y Order.
Category.cs
public class Category
{
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; } = string.Empty;
public ICollection<Product> Products { get; set; } = new List<Product>();
}
Product.cs
public class Product
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; } = string.Empty;
[Precision(10, 2)]
public decimal Price { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; } = null!;
}
Order.cs
public class Order
{
public int Id { get; set; }
public DateTime Date { get; set; } = DateTime.UtcNow;
public ICollection<OrderDetail> Details { get; set; } = new List<OrderDetail>();
}
OrderDetail.cs
public class OrderDetail
{
public int Id { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; } = null!;
public int OrderId { get; set; }
public Order Order { get; set; } = null!;
public int Quantity { get; set; }
}
🗄️ 3. Crear el contexto de base de datos
AppDbContext.cs
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Product> Products => Set<Product>();
public DbSet<Category> Categories => Set<Category>();
public DbSet<Order> Orders => Set<Order>();
public DbSet<OrderDetail> OrderDetails => Set<OrderDetail>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<OrderDetail>()
.HasOne(d => d.Product)
.WithMany()
.HasForeignKey(d => d.ProductId);
modelBuilder.Entity<OrderDetail>()
.HasOne(d => d.Order)
.WithMany(o => o.Details)
.HasForeignKey(d => d.OrderId);
}
}
⚙️ 4. Configurar EF Core en Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.MapControllers();
app.Run();
En appsettings.json agrega la cadena de conexión:
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=DataModelingDemo;Trusted_Connection=True;TrustServerCertificate=True;"
🧰 5. Crear y aplicar migraciones
dotnet ef migrations add InitialCreate
dotnet ef database update
Esto genera la base de datos con todas las tablas y relaciones correctamente modeladas.
✅ Buenas prácticas para el modelado de datos
- Usa convenciones consistentes en nombres y tipos de datos.
- Evita relaciones circulares o dependencias innecesarias.
- Define índices y restricciones para mejorar rendimiento.
- Aplica validaciones con Data Annotations o Fluent API.
- Usa migraciones versionadas para mantener el control del esquema.
⚠️ Errores comunes y cómo evitarlos
| Error | Causa | Solución |
|---|---|---|
| No definir claves primarias | EF Core no infiere correctamente las relaciones | Agrega [Key] o una propiedad Id |
| Relaciones incorrectas | Claves foráneas mal configuradas | Usa HasOne / WithMany en OnModelCreating |
Campos null inesperados | Falta de anotaciones de validación | Usa [Required] y = string.Empty; |
| Migraciones desincronizadas | Cambios sin actualizar la BD | Ejecuta dotnet ef migrations add y update frecuentemente |
❓ Preguntas frecuentes (FAQs)
🧩 ¿Puedo usar EF Core con PostgreSQL o MySQL?
Sí, solo cambia el proveedor NuGet (Npgsql.EntityFrameworkCore.PostgreSQL o Pomelo.EntityFrameworkCore.MySql) y ajusta la cadena de conexión.
💾 ¿Cuándo usar Data Annotations vs Fluent API?
- Data Annotations: para configuraciones simples y legibles.
- Fluent API: para relaciones complejas o reglas específicas.
🚀 ¿Cómo optimizo el rendimiento?
- Usa consultas asíncronas (
await context.Products.ToListAsync();) - Implementa caching para consultas pesadas.
- Habilita tracking selectivo (
AsNoTracking()).

