Esquema de base de datos

Los cambios de modelo no actualizan la BD solos

Si anades un campo, una tabla o una relacion nueva, debes crear migracion y aplicarla. El seed no debe ser la solucion principal para cambios de esquema.

Reglas rapidas
Cambiar modelo Modificar entidad o configuracion EF no cambia la BD por si solo.
Migracion primero El esquema debe evolucionar con migraciones por modulo.
Runtime despues En este CRM, el esquema completo se termina de aplicar en el arranque completo.

Resumen rapido

Paso 1
EF
Cambiar entidad o configuracion EF del modulo.
Paso 2
ADD
Crear migracion del modulo con su DbContext.
Paso 3
UPD
Aplicar migracion o dejar que el arranque use Migrate().
Paso 4
OK
Verificar runtime, seeds y relaciones del modulo.

Como se aplican en este CRM

  • Si el modulo tiene migraciones EF, el runtime intenta Database.Migrate().
  • Si el modulo no tiene migraciones, entra el modo compatibilidad.
  • La aplicacion completa del esquema del modulo ocurre en el arranque completo del CRM.
Subir una DLL no aplica migraciones completas en caliente. La aplicacion completa del esquema se hace cuando la app arranca y reconstruye el ciclo modular.

Configuracion EF recomendada

La forma mas comoda y mantenible es separar cada entidad de su configuracion EF.

public class PROVEEDORESDbContext : DbContext
{
    public DbSet<Proveedor> Proveedores => Set<Proveedor>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(PROVEEDORESDbContext).Assembly);
    }
}

Reglas basicas

Tabla clara Usa ToTable() con nombres de modulo claros.
Indices utiles Define claves de negocio e indices compuestos donde toque.
FK explicita Si dependes de otro maestro, usa FK clara y no dupliques datos.

Explicacion de la configuracion EF

builder.ToTable("PROVEEDORES_Proveedores");
builder.HasKey(x => x.Id);

builder.Property(x => x.CodigoProveedor)
    .HasMaxLength(50)
    .IsRequired();

builder.Property(x => x.FormaPago)
    .HasMaxLength(100);

builder.HasIndex(x => new { x.EmpresaId, x.EntidadId }).IsUnique();
builder.HasIndex(x => new { x.EmpresaId, x.CodigoProveedor });

Tabla y PK

ToTable() fija la tabla real y HasKey() define la clave primaria.

Columnas

Property(), HasMaxLength() e IsRequired() modelan restricciones y nullabilidad.

Indices

HasIndex() mejora busquedas y puede proteger reglas unicas de negocio.

Relaciones

Las FKs deben apuntar a maestros reales, por ejemplo EntidadId hacia ENTIDADES.

Ejemplo de relacion correcta con maestro comun

builder.HasOne<Entidad>()
    .WithMany()
    .HasForeignKey(x => x.EntidadId)
    .OnDelete(DeleteBehavior.Restrict);

Si PROVEEDORES depende de ENTIDADES, lo correcto es enlazar por EntidadId. No debes repetir nombre, direccion o email en la tabla de proveedor.

Comandos base

ENTIDADES

dotnet ef migrations add InitEntidadesComercial `
  --project "C:\Users\msdos\Desktop\crmNuevo\CRM.Web\CRM.Web.csproj" `
  --startup-project "C:\Users\msdos\Desktop\crmNuevo\CRM.Web\CRM.Web.csproj" `
  --context "CRM.Web.Modules.ENTIDADES.Data.ENTIDADESDbContext" `
  --output-dir "Modules\ENTIDADES\Data\Migrations"

PROVEEDORES

dotnet ef migrations add InitProveedores `
  --project "C:\Users\msdos\Desktop\crmNuevo\CRM.Web\CRM.Web.csproj" `
  --startup-project "C:\Users\msdos\Desktop\crmNuevo\CRM.Web\CRM.Web.csproj" `
  --context "CRM.Web.Modules.PROVEEDORES.Data.PROVEEDORESDbContext" `
  --output-dir "Modules\PROVEEDORES\Data\Migrations"

Que genera una migracion

La migracion es el historico de cambios del esquema. Suele incluir operaciones de crear tablas, columnas, indices y restricciones.

migrationBuilder.CreateTable(
    name: "PROVEEDORES_Proveedores",
    columns: table => new
    {
        Id = table.Column<int>(nullable: false),
        EntidadId = table.Column<int>(nullable: false),
        EmpresaId = table.Column<int>(nullable: false),
        CodigoProveedor = table.Column<string>(maxLength: 50, nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_PROVEEDORES_Proveedores", x => x.Id);
    });
Cambiar una clase y compilar no basta. Si no hay migracion aplicada, la base de datos queda atrasada.