【问题标题】:Create and apply migrations for all databases in Entity Framework Core在 Entity Framework Core 中为所有数据库创建和应用迁移
【发布时间】:2016-08-21 18:05:09
【问题描述】:

我有ApplicationDbContext,它动态地将连接字符串更改为数据库,这取决于用户的库名称。所以,对于每个图书馆,我都有自己的数据库。当我创建迁移并应用它们时,它们仅与具有默认连接字符串的默认数据库相关,其中没有定义库名称。

如何对所有这些动态创建的数据库进行迁移并应用迁移,这取决于库名称(它们在创建后存在,它们是完全定义且工作的数据库)?

【问题讨论】:

标签: c# entity-framework migration entity-framework-core entity-framework-migrations


【解决方案1】:

如果我理解正确,您应该执行以下操作:

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
    }
}

DbConfiguration 文件。

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"];

希望对你有帮助。

【讨论】:

  • @YuriyN。如果它适合您并解决您的实际问题,请接受答案。否则,请告诉我,我会改进/扩展它。
  • 老实说,目前我正在处理绝对另一个问题,无法检查,但我会接受这个答案,让其他用户说更多。
猜你喜欢
  • 2019-02-12
  • 2021-01-21
  • 2020-06-06
  • 1970-01-01
  • 2017-10-27
  • 2022-12-09
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
相关资源
最近更新 更多