Uno de los enfoques clásicos al trabajar con bases de datos y Entity Framework es el llamado Data First.
En este modelo, partimos de una base de datos ya existente, y generamos automáticamente las clases C# correspondientes que nos permiten interactuar con ella a través de código.
El enfoque Data First es adecuado ya existe una base de datos con sus tablas, relaciones, claves primarias y foráneas, y queremos trabajar con ella con EF Core.
Esto contrasta con el enfoque Code First: donde escribimos las clases en C# y EF genera la base de datos.
Flujo de trabajo con Database-First
El flujo de trabajo con Database-First consta de los siguientes pasos:
- Tener una base de datos definida: Partimos de una base de datos definida
- Scaffold: Usar el comando para generar las entidades y el DbContext
- Operaciones: Realizar operaciones en la base de datos
Sintaxis básica del comando scaffold
El enfoque Data First se realiza principalmente mediante el comando scaffold, que se encarga de leer la base de datos y generar el código necesario.
dotnet ef dbcontext scaffold "<cadena_conexion>" <proveedor> [opciones]
- “cadena_conexion”: especifica cómo conectar a tu base de datos (no te olvides las
"
comillas"
) - proveedor: proveedor que usaremos
- opciones: opciones adicionales
Opciones útiles
Algunas de las opcionse que podemos usar al a hora de usar el comando scaffold
son,
Opción | Descripción breve |
---|---|
--output-dir | Carpeta donde se generan las clases de entidad. |
--context-dir | Carpeta donde se guarda la clase DbContext . |
--context | Nombre personalizado para el DbContext . |
--schemas | Esquemas específicos a incluir. |
--tables | Tablas específicas a incluir en el modelo. |
--data-annotations | Usa atributos en lugar de Fluent API. |
--no-onconfiguring | Omite la configuración de la cadena de conexión. |
--no-pluralize | Mantiene los nombres originales sin pluralizar. |
--force | Sobrescribe archivos existentes. |
--use-database-names | Usa los nombres exactos de tablas y columnas de la base de datos. |
--no-build | No compila el proyecto antes del scaffold. |
--help | Muestra la ayuda del comando. |
Ejemplo completo del comando
Vamos a verlo mejor con un ejemplo típico de coómo podía ser un comando completo de scaffold
dotnet ef dbcontext scaffold \
"Server=localhost;Database=MiBD;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer \
--output-dir Models \
--context-dir Data \
--context ComercioContext \
--tables Clientes Pedidos \
--no-onconfiguring \
--use-database-names \
--data-annotations \
--force
- Generar clases solo para dos tablas.
Clientes y Pedidos
- Con nombres originales, en carpetas separadas,
- Sin exponer la cadena de conexión en el código
Por supuesto es solo un ejemplo, y tendrás que configurarlo a las necesidades de tu proyecto. Pero, más o menos, te haces una idea
Estructura del código generado
Cuando ejecutemos el comando, y este termine, el resultado es que se nos habrán generado dos cosas.
Una clase DbContext que representa la conexión a la base de datos y contiene un DbSet
por cada tabla:
public partial class MiBaseDeDatosContext : DbContext
{
public virtual DbSet<Cliente> Clientes { get; set; }
public virtual DbSet<Pedido> Pedidos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("cadena_de_conexion");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Aquí EF configura relaciones, claves, etc.
}
}
Una clase por cada tabla, con sus propiedades mapeadas a las columnas:
public partial class Cliente
{
public int Id { get; set; }
public string Nombre { get; set; }
public string Email { get; set; }
}
Estas clases están marcadas como partial
, lo cual permite que podamos extenderlas sin tocar el código generado, lo que es una buena práctica.
No modifiques directamente las clases generadas. Usa partial class
para extenderlas sin perder cambios al regenerar.
Re-generar el modelo tras cambios en la base de datos
Si en alguno momento cambias la base de datos y quieres volver a generar las clases y eliminar primero las anteriores* y ejecutar el comando anterior.
Alternatmivamente, puedes forzar la reescritura usando la opción --force
dotnet ef dbcontext scaffold "cadena" Microsoft.EntityFrameworkCore.SqlServer -o Models --force
El flag --force
sobreescribe archivos existentes.