为Entity Framework Core中的所有数据库创建和应用迁移

时间:2016-04-27 12:29:14

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

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

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

1 个答案:

答案 0 :(得分:2)

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

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

SeedService实施

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

希望对您有帮助。