Entity Framework Core, conocido como EF Core, es el framework oficial de mapeo objeto-relacional (ORM) para aplicaciones .NET. Facilita la interacción con bases de datos relacionales mediante código orientado a objetos, reduciendo la necesidad de escribir SQL manualmente.
Configuración básica y definición del contexto
Para comenzar, se define una clase que hereda de DbContext, la cual representa la sesión con la base de datos y permite consultar y guardar datos.
public class SistemaDbContext : DbContext
{
public DbSet<cliente> Clientes { get; set; }
public DbSet<factura> Facturas { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("Server=localhost;Database=MisDatos;Trusted_Connection=True;");
}
}</factura></cliente>
Configuración de entidades
Las entidades se pueden configurar mediante anotaciones de datos o la API fluida. A continuación, un ejemplo con anotaciones y configuración fluida.
// Uso de atributos
public class Cliente
{
[Key]
public int ClienteId { get; set; }
[Required, MaxLength(200)]
public string NombreCompleto { get; set; }
[Column("email_contacto")]
public string Email { get; set; }
}
// Configuración fluida en OnModelCreating
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Cliente>()
.HasKey(c => c.ClienteId);
modelBuilder.Entity<Cliente>()
.Property(c => c.NombreCompleto)
.IsRequired()
.HasMaxLength(200);
}
Operaciones CRUD esenciales
EF Core simplifica las operaciones de creación, lectura, actualización y eliminación con métodos intuitivos.
// Insertar un registro
var nuevoCliente = new Cliente { NombreCompleto = "María López", Email = "maria@ejemplo.com" };
contexto.Clientes.Add(nuevoCliente);
await contexto.SaveChangesAsync();
// Consultar datos con filtros
var clientes = await contexto.Clientes
.Where(c => c.NombreCompleto.Contains("María"))
.ToListAsync();
// Actualizar un registro existente
var clienteExistente = await contexto.Clientes.FindAsync(101);
clienteExistente.Email = "nuevo_email@ejemplo.com";
await contexto.SaveChangesAsync();
// Eliminar un registro
contexto.Clientes.Remove(clienteExistente);
await contexto.SaveChangesAsync();
Gestión de migraciones
Las migraciones permiten evolucionar el esquema de la base de datos de manera controlada.
# Generar una nueva migración
dotnet ef migrations add EsquemaInicial
# Aplicar cambios a la base de datos
dotnet ef database update
# Exportar script SQL
dotnet ef migrations script --output script.sql
Funcionalidades avanzadas
Consultas con LINQ
EF Core traduce consultas LINQ a SQL, soportando operaciones complejas como inclusiones y proyecciones.
var datos = await contexto.Facturas
.Include(f => f.Cliente)
.Where(f => f.MontoTotal > 200)
.Select(f => new
{
FacturaId = f.FacturaId,
NombreCliente = f.Cliente.NombreCompleto,
f.MontoTotal
})
.ToListAsync();
Transacciones
Para garantizar la atomicidad en múltiples operaciones, se pueden usar transacciones explícitas.
using var trans = await contexto.Database.BeginTransactionAsync();
try
{
// Realizar cambios
await contexto.SaveChangesAsync();
await trans.CommitAsync();
}
catch (Exception ex)
{
await trans.RollbackAsync();
throw;
}
Optimización del rendimiento
EF Core ofrece técnicas para mejorar el desempeño, como consultas sin seguimiento y operaciones en lote.
// Deshabilitar el seguimiento de cambios para consultas de solo lectura
var listaClientes = await contexto.Clientes
.AsNoTracking()
.ToListAsync();
// Actualización masiva (EF Core 7+)
await contexto.Clientes
.Where(c => c.Activo == false)
.ExecuteUpdateAsync(c => c.SetProperty(x => x.UltimoAcceso, DateTime.UtcNow));
Ventajas clave
- Aumenta la productividad al generar consultas SQL automáticamente y ofrecer LINQ con verificación en tiempo de compilación.
- Soporta múltiples bases de datos como SQL Server, PostgreSQL y SQLite, con capacidad multiplataforma.
- Incluye herramientas integradas como migraciones, seguimiento de cambios y control de concurrencia.
- Se integra de forma nativa con ASP.NET Core y el sistema de inyección de dependencias.
Limitaciones notables
- Puede generar consultas SQL ineficientes en casos complejos, con un rendimiento inferior a micro-ORM como Dapper para grandes volúmenes de datos.
- La curva de aprendizaje es pronunciada debido a la amplia variedad de opciones de configuración.
- La flexibilidad se reduce al trabajar con SQL avanzado o características específicas de bases de datos.
- La depuración de consultas generadas y la identificación de problemas de rendimiento pueden ser desafiantes.
Recomendaciones de uso
Ideal para aplicaciones con lógica de negocio compleja, pryoectos de desarrollo rápido donde el esquema de base de datos cambia frecuentemente, y equipos familiarizados con .NET y LINQ.
No recomendado para sistemas con requisitos extremos de rendimiento, proyectos que requieren SQL altamente personalizado, o aplicaciones CRUD simples donde alternativas ligeras podrían ser más adecuadas.
Buenas prácticas incluyen usar AsNoTracking() en consultas de solo lectura, gestionar Include() para evitar el problema N+1, y analizar regularmente las consultas SQL generadas.
Comparación con Dapper
| Aspecto | EF Core | Dapper |
|---|---|---|
| Rendimiento | Moderado | Alto |
| Productividad | Alta | Moderada |
| Facilidad de aprendizaje | Mayor curva | Menor curva |
| Flexbiilidad | Moderada | Alta |
| Soporte para migraciones | Integrado | No disponible |
Para la mayoría de aplicaciones empresariales, EF Core proporciona un equilibrio adecuado entre funcionalidad y facilidad de uso. En módulos críticos para el rendimiento, se puede considerar un enfoque híbrido utilizando EF Core junto con Dapper.