C# 为实体框架核心中的所有数据库创建和应用迁移

C# 为实体框架核心中的所有数据库创建和应用迁移,c#,entity-framework,migration,entity-framework-core,entity-framework-migrations,C#,Entity Framework,Migration,Entity Framework Core,Entity Framework Migrations,我有ApplicationDbContext,它可以动态地将连接字符串更改为数据库,这取决于用户的库名。因此,对于每个库,我都有自己的数据库。当我创建迁移并应用它们时,它们只与带有默认连接字符串的默认数据库相关,其中没有定义库名称 我如何对所有这些动态创建的数据库进行迁移和应用迁移,这取决于库名称(它们在创建之后就存在,它们是完全定义的和工作的数据库)?如果我正确理解您的意思,您应该实现以下几点: 1) 实现将迁移架构和种子数据的服务。(不管他们在过去做了什么,我还是更喜欢我的实现) 助手

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


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

如果我正确理解您的意思,您应该实现以下几点:

1) 实现将迁移架构和种子数据的服务。(不管他们在过去做了什么,我还是更喜欢我的实现)

助手

    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();
        }
    }
种子服务实现

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

我希望它能对您有所帮助。

您可以使用基于代码的迁移,迭代每个连接字符串:@SteveGreene这不适用于EF Core。是的,EF Core非常原始。你可能会在Startup.cs文件@SteveGreene中找到一个提示。真的,我找不到。你的确切意思是什么?他的startup.cs中有执行迁移的代码。我没有看到太多关于它的文档,但也许它会给你一个提示。请参阅serviceScope.ServiceProvider.GetService().Database.Migrate()附近的行@尤里恩。若它对你们有效并且解决了你们真正的问题,请接受答案。否则,让我知道,我会改进/扩展它。老实说,目前我正在处理另一个问题,无法检查,但我会接受这个答案,让其他用户说更多。
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>();
}
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
    }
}
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"];