entity-framework-database-first

Database First en Entity Framework

  • 4 min

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:

  1. Tener una base de datos definida: Partimos de una base de datos definida
  2. Scaffold: Usar el comando para generar las entidades y el DbContext
  3. 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ónDescripción breve
--output-dirCarpeta donde se generan las clases de entidad.
--context-dirCarpeta donde se guarda la clase DbContext.
--contextNombre personalizado para el DbContext.
--schemasEsquemas específicos a incluir.
--tablesTablas específicas a incluir en el modelo.
--data-annotationsUsa atributos en lugar de Fluent API.
--no-onconfiguringOmite la configuración de la cadena de conexión.
--no-pluralizeMantiene los nombres originales sin pluralizar.
--forceSobrescribe archivos existentes.
--use-database-namesUsa los nombres exactos de tablas y columnas de la base de datos.
--no-buildNo compila el proyecto antes del scaffold.
--helpMuestra 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.