Как выполнить миграцию базы данных при запуске при использовании Autofa c .AspNetCore.Multitenant в. NET Core 3.x? - PullRequest
2 голосов
/ 22 января 2020

В однопользовательском режиме. NET Базовые приложения, миграции базы данных EF Core (и заполнение БД) могут выполняться сразу после создания IHost (обычно в Program.cs):

await BuildHost(args)
    .MigrateDbContext<I.MyDbContext>()
    .RunAsync();
}

поскольку к этому моменту был зарегистрирован единственный-единственный контекст БД.

В мультитенантных приложениях специфичные для арендатора c регистрации выполняются намного позже - в multitenantContainer.ConfigureTenant(...) обратный вызов - как только HTTPContext станет доступным.

Проблема заключается в том, что после выполнения этого обратного вызова, похоже, не существует места, где можно получить контекст c, определяемый арендатором, для вызова Миграция.

Я уверен, что это неправильно делать в конце обратного вызова multitenantContainer.ConfigureTenant(...), поскольку функция этого, по-видимому, состоит исключительно из регистрации компонента.

Где должна выполняться миграция от

Ответы [ 2 ]

1 голос
/ 23 января 2020

Я достиг этого, используя Aufofa c s OnActivated().

in Startup.cs:

public static MultitenantContainer ConfigureMultitenantContainer(IContainer container)
{
    // retrieve tenant settings
    CONFIG.Tenancy tenancyConfig = null;
    var tenancyOptions = container.Resolve<IOptions<CONFIG.Tenancy>>();
    if (tenancyOptions != null)
        tenancyConfig = tenancyOptions.Value;

    // create multitenant container
    var accessor = container.Resolve<IHttpContextAccessor>();
    var tenantIdentificationStrategy = new HELP.RequestHeaderTenantIdentificationStrategy(accessor, tenancyOptions, container);
    var multitenantContainer = new MultitenantContainer(tenantIdentificationStrategy, container);

    // configure tenant-specific dependencies here
    foreach (CONFIG.Tenant tenancy in tenancyConfig.Tenant)
    {
        multitenantContainer.ConfigureTenant(tenancy.Token, containerBuilder =>
        {
            containerBuilder
                .Register(componentContext =>
                {
                    var serviceProvider = componentContext.Resolve<IServiceProvider>();
                    var dbContextOptions = new DbContextOptions<I.ProjectsContext>(new Dictionary<Type, IDbContextOptionsExtension>());

                    var optionsBuilder = new DbContextOptionsBuilder<I.ProjectsContext>(dbContextOptions)
                        .EnableSensitiveDataLogging()
                        .EnableDetailedErrors()
                        .UseApplicationServiceProvider(serviceProvider)
                        .UseMySql(
                            tenancy.DBConnection.Projects,
                            serverOptions => serverOptions.EnableRetryOnFailure(
                                maxRetryCount: 5,
                                maxRetryDelay: TimeSpan.FromSeconds(30),
                                errorNumbersToAdd: null));

                    return optionsBuilder.Options;
                })
                .As<DbContextOptions<I.ProjectsContext>>()
                .InstancePerDependency();

            containerBuilder.Register(componentContext => componentContext.Resolve<DbContextOptions<I.ProjectsContext>>())
                .As<DbContextOptions>()
                .InstancePerDependency();

            containerBuilder.RegisterType<I.ProjectsContext>()
                .AsSelf()
                .InstancePerDependency()
                .OnActivated(sr =>
                    // migrate database after the component is activated
                    sr.Instance.Database.MigrateAsync());
        });
    }

    return multitenantContainer;
}
1 голос
/ 23 января 2020

Вы можете зарегистрировать компонент IStartable внутри каждого арендатора, чтобы начать процесс миграции.

public class AutomigrateDatabase : IStartable
{
   public void AutomigrateDatabase(XContext xContext)
   {
       this._xContext = xContext; 
   }

   private readonly XContext _xContext; 

   public void Start()
   {
      this._xContext.Database.Migrate(); 
   }
}

и зарегистрируйте его следующим образом:

mtc.ConfigureTenant('1', b => {
    b.RegisterType<AutomigrateDatabase>().As<IStartable>().SingleInstance();
});

Более подробную информацию о стартовом коде можно найти в документации: Запуск кода при запуске

...