Jeff Dege
Jeff Dege

Reputation: 11680

How do I direct log output to a file, using a FluentMigrator v3.2.15 In-Process runner?

I have a .NET 4.5.2 migration runner built using FluentMigrator 2.0.7 that "m trying to move to .NET 5.0 and FluentMigrator 3.2.15.

My current difficulty is writing the output to a text file.

var serviceProvider = new ServiceCollection()

    .AddSingleton<ILoggerProvider, SqlScriptFluentMigratorLoggerProvider>()
    
    .Configure<LogFileFluentMigratorLoggerOptions>(o => {
        o.OutputFileName = "MyFilename.log";
    })

    .AddLogging(lb => lb.AddFluentMigratorConsole())
    .Configure<FluentMigratorLoggerOptions>(o =>
    {
        o.ShowSql = true;
        o.ShowElapsedTime = true;
    })

    .AddFluentMigratorCore()

    .ConfigureRunner(builder => 
        builder
            .AddSqlServer2016()
            .WithGlobalConnectionString(this.options.connectionString.ExpandDataDirectory())
            .WithMigrationsIn(this.assembly)
        )
    
    .BuildServiceProvider();

using (var scope = serviceProvider.CreateScope())
{
    var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();

    if (this.options.reverseMigration)
        runner.MigrateDown(0);
    else
        runner.MigrateUp();
}

My problem is simple - when I try to run the migration I get an error:

Unable to resolve service for type 'System.IO.TextWriter' while attempting to activate 'FluentMigrator.Runner.Logging.SqlScriptFluentMigratorLoggerProvider'.

What's going on is simple enough - TextWriter is an abstract class, it can't be initiated.

But how do I configured the ServiceProvider so that when it's asked for a TextWriter, it returns a StreamWriter writing to the OutputFileName I provided to LogFileFluentMigratorLoggerOptions?

===

Edited:

I can do this:

using var logStream = new FileStream(this.options.outputFilename, FileMode.Append);
using var sw = new StreamWriter(logStream);

var serviceProvider = new ServiceCollection()

    .AddSingleton<TextWriter>(sw)

    .AddSingleton<ILoggerProvider, SqlScriptFluentMigratorLoggerProvider>()

    ...

But it strikes me as being very ugly...

Upvotes: 2

Views: 1487

Answers (1)

Thomas
Thomas

Reputation: 51

I could write an sql output to a text file by registering LogFileFluentMigratorLoggerProvider as a singleton and then configuring it. LogFileFluentMigratorLoggerProvider inherits from SqlScriptFluentMigratorLoggerProvider and takes care to instantiate a StreamWriter for you.

private static IServiceProvider CreateServices()
{
   // var connectionString = ""; grab your connection string
   return new ServiceCollection()
              .AddFluentMigratorCore()
              .ConfigureRunner(rb => rb
                  .AddSqlServer2016()
                  .WithGlobalConnectionString(connectionString)
                  .WithMigrationsIn(this.assembly))
              .AddLogging(lb => lb.AddFluentMigratorConsole())
              .AddSingleton<ILoggerProvider, LogFileFluentMigratorLoggerProvider>()
              .Configure<LogFileFluentMigratorLoggerOptions>(
                 opt =>
                 {
                     opt.OutputFileName = "C:\\TEMP\\DatabaseMigration.sql";
                     opt.OutputGoBetweenStatements = true;
                     opt.ShowSql = true;
                 })
              .BuildServiceProvider(false);
}

Upvotes: 1

Related Questions