FluentMigrator: как установить схему по умолчанию для MigrationRunner

У меня многопользовательская база данных. Специфичные для арендатора данные хранятся внутри его собственной (PostgreSQL) схемы.

Я хотел бы иметь возможность использовать FluentMigrator для развертывания новых арендаторов по мере необходимости. Я настроил пример на GitHub, где HTTP-публикация на конечную точку будет развертывать схему. Однако по умолчанию развертывает его в общедоступной схеме. Я хотел бы иметь возможность указать схему для развертывания.

I.e.

public class TenantService: ITenantService {
  private readonly IServiceProvider _provider;

  public TenantService(IServiceProvider provider) {
    _provider = provider;
  }

  public void Create(string tenantName) {
    using(var scope = _provider.CreateScope()) {
      var migrationRunner = scope.ServiceProvider.GetService<IMigrationRunner>();
      // TODO:  Set the default schema = tenantName
      migrationRunner.MigrateUp();
    }
  }
}

Как установить схему по умолчанию для MigrationRunner?

Изменить: я обновил репозиторий GitHub, чтобы отразить принятый ответ.


person Andy N    schedule 27.06.2020    source источник


Ответы (1)


Я боролся с этой же проблемой, а также с той же средой. .Net-core, FluentMigrator и Postgre с разными схемами. Я использовал устаревшие функции и уже заметил, что мне нужно создать свой собственный: ConventionSet. Я смог исправить это в следующем, где я сначала должен сказать: Спасибо за ваш git, это также помогло мне разобраться в моей проблеме, вот:

Первое, что я сделал, это вручную создал базу данных и схему с другим именем: public. Затем я поправил файл startup.cs.

        // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IConventionSet>(new DefaultConventionSet("tenanta", null));
        services.AddFluentMigratorCore();
        services.ConfigureRunner(rb => rb
                .AddPostgres()                    
                .WithGlobalConnectionString("Server=localhost;Port=5432;User Id=postgres;Password=12345678;CommandTimeout=20;database=nameofdatabase")
                .ScanIn(typeof(AddSecuritySchema).Assembly).For.Migrations());
        services.AddSingleton<ITenantService, TenantService>();
        services.AddControllers();
    }

С приведенным выше изменением, когда мы добавляем: новый DefaultConventionSet с именем схемы, я, наконец, мог запускать миграции в другой схеме, а не в общедоступной. Но я также хочу, чтобы это было на лету. Итак, чтобы добиться этого (не уверен, что правильно) я сделал следующее:

public class TenantService: ITenantService {
    private readonly IServiceProvider _provider;
    public TenantService(IServiceProvider provider) {
        _provider = provider;
    }

    public void Create(string tenantName) {

        var serviceProvider = new ServiceCollection()
                        .AddSingleton<IConventionSet>(new DefaultConventionSet(tenantName, null))
                        .AddFluentMigratorCore()
                        .ConfigureRunner(r => r.AddPostgres()
                                                .WithGlobalConnectionString("Server=localhost;Port=5432;User Id=postgres;Password=12345678;CommandTimeout=20;database=databasename")
                                                .WithRunnerConventions(new MigrationRunnerConventions()
                                                {

                                                })
                                                .ScanIn(typeof(AddSecuritySchema).Assembly).For.Migrations()
                        )
                        .Configure<RunnerOptions>(opt =>
                        {
                            opt.TransactionPerSession = true;
                        })
                        .BuildServiceProvider(false);

        using (var scope = serviceProvider.CreateScope())
        {
            var migrationRunner = scope.ServiceProvider.GetService<IMigrationRunner>();
            migrationRunner.MigrateUp();
        }
    }
}

Конечно, важно сначала зарегистрировать ConventionSet ;)

person Leroy Meijer    schedule 29.08.2020