代码之家  ›  专栏  ›  技术社区  ›  Andy N

FluentMigrator:如何为MigratreRunner设置默认架构

  •  0
  • Andy N  · 技术社区  · 4 年前

    我有一个多租户数据库。租户特定的数据存储在它自己的(PostgreSQL)模式中。

    我希望能够使用FluentMigrator根据需要部署新租户。我已经建立了一个 example on GitHub 其中,向端点发送HTTP帖子将部署模式。但是,默认情况下会将其部署到公共架构。我希望能够指定要部署到的架构。

    即。

    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();
        }
      }
    }
    

    如何设置MigratREunner的默认架构?

    编辑: 我已经更新了GitHub仓库,以反映已接受的答案。

    0 回复  |  直到 4 年前
        1
  •  3
  •   Leroy Meijer    4 年前

    我一直在与这个完全相同的问题和同样的环境作斗争。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();
        }
    

    通过上述更改,我们添加了一个:new DefaultConventionSet和schemaname,我终于可以在不同的模式上运行迁移,而不是公共模式。但我也希望它能在飞行中。因此,为了实现这一点(不确定是否正确),我做了以下工作:

    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();
            }
        }
    }
    

    当然,首先注册约定集很重要;)