I have console app that uses FluentMigrator migrations, but now I need to implement user confirmation before actual migration process. I got into repo sources, found out about version loader and how to get unapplied list of migrations using IServiceProvider
. But can't find a way yet to print SQL script of the migration that will be used in the MigrateUp()
. I am using SQL Server package as well. Could anyone point a direction?
private static void UpdateDatabase(IServiceProvider serviceProvider)
{
var runner = serviceProvider.GetRequiredService<IMigrationRunner>();
var versionLoader = serviceProvider.GetRequiredService<IVersionLoader>();
var migrationContext = serviceProvider.GetRequiredService<IMigrationContext>();
var migrations = runner.MigrationLoader.LoadMigrations()
.Where(migration => !versionLoader.VersionInfo.HasAppliedMigration(migration.Key))
.ToList();
// print migrations up expressions
foreach (var migration in migrations)
{
Console.WriteLine($"Pending migration: {migration.Value.GetName()}");
Console.WriteLine("SQL:");
migration.Value.Migration.GetUpExpressions(migrationContext);
foreach (var expression in migrationContext.Expressions)
{
Console.WriteLine(expression); // this just outputs "CreateTable Test" in my case
}
}
bool userAccepted = true; // TODO: get confirmation from user
if (!userAccepted)
return;
// Execute the migrations
runner.MigrateUp();
}
There is IMigrationGenerator
that can be resolved by using IServiceProvider
. But, unfortunately, there are no methods that support IMigrationExpression
parameter (see below), so I had to write either wall of if-else
statements for each type or use a reflection. I used second option. Maybe there is better approach?
var migrationGenerator = serviceProvider.GetRequiredService<IMigrationGenerator>();
// print migrations up expressions
foreach (var migration in migrations)
{
Console.WriteLine($"Pending migration: {migration.Value.GetName()}");
Console.WriteLine("SQL:");
migration.Value.Migration.GetUpExpressions(migrationContext);
foreach (var expression in migrationContext.Expressions)
{
if (expression is ExecuteSqlScriptExpression executeSqlScriptExpression)
{
Console.WriteLine(executeSqlScriptExpression.SqlScript);
}
else if (expression is ExecuteSqlStatementExpression executeSqlStatementExpression)
{
Console.WriteLine(executeSqlStatementExpression.SqlStatement);
}
else
{
var processMethod = migrationGenerator.GetType().GetMethod("Generate", new[] { expression.GetType() });
var sql = (string)processMethod.Invoke(migrationGenerator, new[] { expression });
Console.WriteLine(sql);
}
}
}