Entity framework core 在.NET Core 3.x中使用Autofac.AspNetCore.Multitenant时,如何在启动时执行数据库迁移?
在单租户.NET Core应用程序中,EF Core数据库迁移(和数据库种子设定)可以在IHost构建后立即执行(通常在Program.cs中):Entity framework core 在.NET Core 3.x中使用Autofac.AspNetCore.Multitenant时,如何在启动时执行数据库迁移?,entity-framework-core,autofac,database-migration,multi-tenant,asp.net-core-3.0,Entity Framework Core,Autofac,Database Migration,Multi Tenant,Asp.net Core 3.0,在单租户.NET Core应用程序中,EF Core数据库迁移(和数据库种子设定)可以在IHost构建后立即执行(通常在Program.cs中): 等待构建主机(args) .MigrateDbContext() .RunAsync(); } 因为到目前为止,唯一的数据库上下文已经注册 在多租户应用程序中,HTTPContext可用后,multitenantContainer.ConfigureTenant(…)回调中的 问题是,在执行此回调之后,似乎没有位置可以检索特定于租户的上下文以调用迁
等待构建主机(args)
.MigrateDbContext()
.RunAsync();
}
因为到目前为止,唯一的数据库上下文已经注册
在多租户应用程序中,HTTPContext可用后,multitenantContainer.ConfigureTenant(…)回调中的
问题是,在执行此回调之后,似乎没有位置可以检索特定于租户的上下文以调用迁移
我确信在multitenantContainer.ConfigureTenant(…)
回调结束时执行此操作是错误的,因为它的功能似乎纯粹是组件注册
迁移应该从何处执行?您可以在每个租户内注册一个
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();
});
mtc.ConfigureTenant('1',b=>{
b、 RegisterType我使用Aufofac的OnActivated()
实现了这一点
在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;
}
公共静态多租户容器配置多租户容器(IContainer容器)
{
//检索租户设置
CONFIG.Tenancy-CONFIG=null;
var tenacyoptions=container.Resolve();
if(租户选项!=null)
tenacyconfig=tenacycoptions.Value;
//创建多租户容器
var accessor=container.Resolve();
var tenantIdentificationStrategy=new HELP.RequestHeaderTenantIdentificationStrategy(访问者、租户选项、容器);
var multitenantContainer=新的multitenantContainer(租户身份识别策略,容器);
//在此处配置特定于租户的依赖项
foreach(tenacyconfig.Tenant中的CONFIG.Tenant租约)
{
multitenantContainer.ConfigureTenant(tenancy.Token,containerBuilder=>
{
集装箱船
.Register(组件上下文=>
{
var serviceProvider=componentContext.Resolve();
var dbContextOptions=newdbcontextoptions(newdictionary());
var optionsBuilder=new DbContextOptionsBuilder(dbContextOptions)
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
.UseApplicationServiceProvider(服务提供者)
.UseMySql(
tenancy.DBConnection.Projects,
serverOptions=>serverOptions.EnableRetryOnFailure(
最大计数:5,
maxRetryDelay:TimeSpan.FromSeconds(30),
errorNumbersToAdd:null));
返回选项生成器。选项;
})
.As()
.InstancePerDependence();
containerBuilder.Register(componentContext=>componentContext.Resolve())
.As()
.InstancePerDependence();
containerBuilder.RegisterType()
.AsSelf()
.InstancePerDependency()实例
.on已激活(sr=>
//在激活组件后迁移数据库
sr.Instance.Database.MigrateAsync());
});
}
返回多租户容器;
}
这是实体框架吗?DbUp?可以添加一些标签来帮助合适的人看到这一点。它是EF Core。很好-编辑并交换了一个标签(已经使用了最多五个!)Hi Cyril,不幸的是,自从开始()IStartable
的方法在容器构建后会被调用,但是ConfigureTenant()
直到稍后才会被调用。为了澄清这一点,在ConfigureTenant()
内部设置的每个租户回调直到稍后才会被调用。
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;
}