feat: Add initial database migration with FluentMigrator
This commit is contained in:
		| @@ -14,6 +14,7 @@ | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <ProjectReference Include="..\Mercados.Infrastructure\Mercados.Infrastructure.csproj" /> | ||||
|     <ProjectReference Include="..\Mercados.Database\Mercados.Database.csproj" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
| </Project> | ||||
|   | ||||
| @@ -1,20 +1,54 @@ | ||||
| // Importamos los namespaces necesarios | ||||
| using FluentMigrator.Runner; // <--- AÑADIR | ||||
| using Mercados.Database.Migrations; // <--- AÑADIR | ||||
| using Mercados.Infrastructure; | ||||
| using Mercados.Infrastructure.Persistence; | ||||
| using System.Reflection; // <--- AÑADIR | ||||
|  | ||||
| var builder = WebApplication.CreateBuilder(args); | ||||
|  | ||||
| // 1. Registramos nuestra fábrica de conexiones como un Singleton. | ||||
| // Solo se creará una instancia que leerá la configuration una vez. | ||||
| // --- V INICIO DE NUESTRO CÓDIGO V --- | ||||
|  | ||||
| // 1. Registramos nuestra fábrica de conexiones. | ||||
| builder.Services.AddSingleton<IDbConnectionFactory, SqlConnectionFactory>(); | ||||
|  | ||||
| // 2. Configurar FluentMigrator | ||||
| builder.Services | ||||
|     .AddFluentMigratorCore() | ||||
|     .ConfigureRunner(rb => rb | ||||
|         // Usar el conector para SQL Server | ||||
|         .AddSqlServer() | ||||
|         // Obtener la cadena de conexión desde appsettings.json | ||||
|         .WithGlobalConnectionString(builder.Configuration.GetConnectionString("DefaultConnection")) | ||||
|         // Definir el ensamblado (proyecto) que contiene las migraciones | ||||
|         .ScanIn(typeof(CreateInitialTables).Assembly).For.Migrations()) | ||||
|     // Habilitar el logging para ver qué hacen las migraciones en la consola | ||||
|     .AddLogging(lb => lb.AddFluentMigratorConsole()); | ||||
|  | ||||
|  | ||||
| // --- ^ FIN DE NUESTRO CÓDIGO ^ --- | ||||
|  | ||||
| // Add services to the container. | ||||
| builder.Services.AddControllers(); | ||||
| // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | ||||
| builder.Services.AddEndpointsApiExplorer(); | ||||
| builder.Services.AddSwaggerGen(); | ||||
|  | ||||
| var app = builder.Build(); | ||||
|  | ||||
| // --- V INICIO DE NUESTRO CÓDIGO DE EJECUCIÓN V --- | ||||
|  | ||||
| // 3. Ejecutar las migraciones al iniciar la aplicación (ideal para desarrollo y despliegues sencillos) | ||||
| // Obtenemos el "scope" de los servicios para poder solicitar el MigrationRunner | ||||
| using (var scope = app.Services.CreateScope()) | ||||
| { | ||||
|     var migrationRunner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>(); | ||||
|     // Ejecuta las migraciones pendientes | ||||
|     migrationRunner.MigrateUp(); | ||||
| } | ||||
|  | ||||
| // --- ^ FIN DE NUESTRO CÓDIGO DE EJECUCIÓN ^ --- | ||||
|  | ||||
|  | ||||
| // Configure the HTTP request pipeline. | ||||
| if (app.Environment.IsDevelopment()) | ||||
| { | ||||
|   | ||||
| @@ -0,0 +1,70 @@ | ||||
| using FluentMigrator; | ||||
|  | ||||
| namespace Mercados.Database.Migrations | ||||
| { | ||||
|     // El número es la versión única de esta migración. | ||||
|     // Usar un timestamp es una práctica común y segura. | ||||
|     [Migration(20250701113000)] | ||||
|     public class CreateInitialTables : Migration | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Define las acciones a realizar para aplicar la migración (crear tablas, etc.). | ||||
|         /// </summary> | ||||
|         public override void Up() | ||||
|         { | ||||
|             // --- Tabla para Cotizaciones de Ganado --- | ||||
|             Create.Table("CotizacionesGanado") | ||||
|                 .WithColumn("Id").AsInt64().PrimaryKey().Identity() // Usamos Int64 (long) para los IDs | ||||
|                 .WithColumn("Categoria").AsString(100).NotNullable() | ||||
|                 .WithColumn("Especificaciones").AsString(200).NotNullable() | ||||
|                 .WithColumn("Maximo").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("Minimo").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("Promedio").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("Mediano").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("Cabezas").AsInt32().NotNullable() | ||||
|                 .WithColumn("KilosTotales").AsInt32().NotNullable() | ||||
|                 .WithColumn("KilosPorCabeza").AsInt32().NotNullable() | ||||
|                 .WithColumn("ImporteTotal").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("FechaRegistro").AsDateTime().NotNullable(); | ||||
|  | ||||
|             // --- Tabla para Cotizaciones de Granos --- | ||||
|             Create.Table("CotizacionesGranos") | ||||
|                 .WithColumn("Id").AsInt64().PrimaryKey().Identity() | ||||
|                 .WithColumn("Nombre").AsString(50).NotNullable() | ||||
|                 .WithColumn("Precio").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("VariacionPrecio").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("FechaOperacion").AsDateTime().NotNullable() | ||||
|                 .WithColumn("FechaRegistro").AsDateTime().NotNullable(); | ||||
|  | ||||
|             // --- Tabla para Cotizaciones de Bolsa --- | ||||
|             Create.Table("CotizacionesBolsa") | ||||
|                 .WithColumn("Id").AsInt64().PrimaryKey().Identity() | ||||
|                 .WithColumn("Ticker").AsString(20).NotNullable() | ||||
|                 .WithColumn("Mercado").AsString(50).NotNullable() // "EEUU", "Local" | ||||
|                 .WithColumn("PrecioActual").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("Apertura").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("CierreAnterior").AsDecimal(18, 2).NotNullable() | ||||
|                 .WithColumn("PorcentajeCambio").AsDecimal(18, 4).NotNullable() // Más precisión para porcentajes | ||||
|                 .WithColumn("FechaRegistro").AsDateTime().NotNullable(); | ||||
|  | ||||
|             // --- Tabla para auditar las fuentes de datos --- | ||||
|             Create.Table("FuentesDatos") | ||||
|                 .WithColumn("Id").AsInt64().PrimaryKey().Identity() | ||||
|                 .WithColumn("Nombre").AsString(100).NotNullable().Unique() // El nombre debe ser único | ||||
|                 .WithColumn("UltimaEjecucionExitosa").AsDateTime().NotNullable() | ||||
|                 .WithColumn("Url").AsString(500).Nullable(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Define las acciones para revertir la migración (eliminar las tablas). | ||||
|         /// Esto es útil si necesitas deshacer un cambio. | ||||
|         /// </summary> | ||||
|         public override void Down() | ||||
|         { | ||||
|             Delete.Table("FuentesDatos"); | ||||
|             Delete.Table("CotizacionesBolsa"); | ||||
|             Delete.Table("CotizacionesGranos"); | ||||
|             Delete.Table("CotizacionesGanado"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user