为 Entity Framework Core 中的所有数据库创建和应用迁移
Create and apply migrations for all databases in Entity Framework Core
我有 ApplicationDbContext
,它根据用户的库名称动态地将连接字符串更改为数据库。因此,对于每个图书馆,我都有自己的数据库。当我创建迁移并应用它们时,它们仅与具有默认连接字符串的默认数据库相关,其中没有定义库名称。
我如何对所有这些动态创建的数据库进行迁移并应用迁移,这些数据库取决于库名称(它们在创建后存在,它们是完全定义的工作数据库)?
如果我理解正确,你应该执行以下操作:
1) 实施将迁移您的模式和种子数据的服务。 (尽管他们在 latest version 中做了什么,我仍然更喜欢我的实现)
帮手
public static async Task EnsureSeedData(IServiceProvider serviceProvider)
{
using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
// here could be several seed services if necessary
var seedService = scope.ServiceProvider.GetService<ISeedService>();
await seedService.MigrateAsync();
await seedService.SeedAsync();
}
}
ISeedService 接口
internal interface ISeedService
{
Task MigrateAsync();
Task SeedAsync();
}
种子服务实施
internal sealed class SeedService : ISeedService
{
private readonly InitializeContext _identityContext;
public SeedService(InitializeContext identityContext)
{
_identityContext = identityContext;
}
public async Task MigrateAsync()
{
await _identityContext.Database.MigrateAsync();
}
public async Task SeedAsync()
{
if (_identityContext.AllMigrationsApplied())
{
var strategy = _identityContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
using (var transaction = await _identityContext.Database.BeginTransactionAsync())
{
// seed data if necessary
transaction.Commit();
}
});
}
}
}
Program.cs 文件
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
Task.Run(async () =>
{
await SeedData.EnsureSeedData(host.Services);
}).Wait();
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
2) 在 DI 中注册上下文和相关服务,这将允许动态检索连接字符串。有多种方法,我的实现不是最好的,所以由你决定。
Startup.cs 文件
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISeedService, SeedService>();
services.AddScoped<IDbConfiguration, FakeDbConfiguration>();
services.AddDbContext<InitializeContext>((provider, builder) =>
{
var dbConfiguration = provider.GetService<IDbConfiguration>();
builder.UseSqlServer(dbConfiguration.Connection);
});
// omitted
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// omitted
}
}
Db 配置文件。
internal sealed class FakeDbConfiguration : IDbConfiguration
{
private readonly IConfiguration _configuration;
public FakeDbConfiguration(IConfiguration configuration)
{
_configuration = configuration;
}
// REPLACE THIS PART WITH YOURS IMPLEMENTATION
public string Connection => _configuration["Database:Connection"];
希望对你有所帮助
我有 ApplicationDbContext
,它根据用户的库名称动态地将连接字符串更改为数据库。因此,对于每个图书馆,我都有自己的数据库。当我创建迁移并应用它们时,它们仅与具有默认连接字符串的默认数据库相关,其中没有定义库名称。
我如何对所有这些动态创建的数据库进行迁移并应用迁移,这些数据库取决于库名称(它们在创建后存在,它们是完全定义的工作数据库)?
如果我理解正确,你应该执行以下操作:
1) 实施将迁移您的模式和种子数据的服务。 (尽管他们在 latest version 中做了什么,我仍然更喜欢我的实现)
帮手
public static async Task EnsureSeedData(IServiceProvider serviceProvider)
{
using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
// here could be several seed services if necessary
var seedService = scope.ServiceProvider.GetService<ISeedService>();
await seedService.MigrateAsync();
await seedService.SeedAsync();
}
}
ISeedService 接口
internal interface ISeedService
{
Task MigrateAsync();
Task SeedAsync();
}
种子服务实施
internal sealed class SeedService : ISeedService
{
private readonly InitializeContext _identityContext;
public SeedService(InitializeContext identityContext)
{
_identityContext = identityContext;
}
public async Task MigrateAsync()
{
await _identityContext.Database.MigrateAsync();
}
public async Task SeedAsync()
{
if (_identityContext.AllMigrationsApplied())
{
var strategy = _identityContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
using (var transaction = await _identityContext.Database.BeginTransactionAsync())
{
// seed data if necessary
transaction.Commit();
}
});
}
}
}
Program.cs 文件
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
Task.Run(async () =>
{
await SeedData.EnsureSeedData(host.Services);
}).Wait();
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
2) 在 DI 中注册上下文和相关服务,这将允许动态检索连接字符串。有多种方法,我的实现不是最好的,所以由你决定。
Startup.cs 文件
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISeedService, SeedService>();
services.AddScoped<IDbConfiguration, FakeDbConfiguration>();
services.AddDbContext<InitializeContext>((provider, builder) =>
{
var dbConfiguration = provider.GetService<IDbConfiguration>();
builder.UseSqlServer(dbConfiguration.Connection);
});
// omitted
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// omitted
}
}
Db 配置文件。
internal sealed class FakeDbConfiguration : IDbConfiguration
{
private readonly IConfiguration _configuration;
public FakeDbConfiguration(IConfiguration configuration)
{
_configuration = configuration;
}
// REPLACE THIS PART WITH YOURS IMPLEMENTATION
public string Connection => _configuration["Database:Connection"];
希望对你有所帮助