Search code examples
c#migrationfluent-migratorsqlmigrations

C# FluentMigrator.Runner console app set transaction per session


I am using FlunetMigrator.Runner.3.2.1 and see that this version no longer defaults to rolling back all migrations is one of them fails. It says they are per migration file! which doesn't add value. Is there a way to set the transaction per session whilst running it as a .net core console app.

I see there is this link https://fluentmigrator.github.io/articles/runners/runner-console.html but says use the Migrate.exe file which we are not using, we are using a console. Can I set the transaction level to session in the code?

Why would anyone want to run it and only have some of the changes done, All or nothing is a much better approach


Solution

  • I found the answer! you set it in the Runner options as shown below

    opt.TransactionPerSession = true;
    

    Full method that create the IServiceProvide

    private static IServiceProvider CreateServices(string connectionString,
        CommandLineArguments commandLineArguments)
    {
        return new ServiceCollection()
            // Add common FluentMigrator services
            .AddFluentMigratorCore()
            .ConfigureRunner(rb => rb
                // Add SQL Server support to FluentMigrator
                .AddSqlServer()
                // Set the connection string
                .WithGlobalConnectionString(connectionString)
                
                // Define the assembly containing the migrations
                .ScanIn(typeof(Program).Assembly).For.Migrations().For.EmbeddedResources())
            // Enable logging to console in the FluentMigrator way
            .AddLogging(lb => lb.AddFluentMigratorConsole())
            .Configure<RunnerOptions>(opt => { 
                opt.Tags = commandLineArguments.Tags.ToArray();
                opt.TransactionPerSession = true; })
            // Build the service provider
            .BuildServiceProvider(false);
    }
    

    The below code is the full example that uses the IServiceProvider

    var serviceProvider = CreateServices(connectionString, commandLineArguments);
    
    // Put the database update into a scope to ensure
    // that all resources will be disposed.
    using (var scope = serviceProvider.CreateScope())
    {
        try
        {
            UpdateDatabase(scope.ServiceProvider, commandLineArguments);
        }
        catch (Exception e)
        {
            Console.WriteLine("There was a problem with the migration: " + e.Message + "\n" +
                              e.StackTrace);
        }
        migrationRun = true;
    }
    

    The Update Database code:

    private static void UpdateDatabase(IServiceProvider serviceProvider, CommandLineArguments commandLineArguments)
    {
        // Instantiate the runner
        var runner = serviceProvider.GetRequiredService<IMigrationRunner>();
    
        if (commandLineArguments.Downgrade)
        {
            runner.MigrateDown(commandLineArguments.Version != -1 ? commandLineArguments.Version : 0);
        }
        else
        {
            if (commandLineArguments.Version != -1)
            {
                runner.MigrateUp(commandLineArguments.Version);
            }
            else
            {
                runner.MigrateUp();
            }
    
        }
    }