Create and apply migrations for all databases in Entity Framework Core

c# ef-migrations entity-framework entity-framework-core migration

Question

I have ApplicationDbContext, which dynamically change connection string to database, which depends on user's library name. So, for each library, I have it's own database. When I'm creating migrations and apply them, they are related only to default database with default connection string, where no library name defined.

How can I make and apply migrations to all this databases, that dynamically created, that depends on library name (they exist after creation, they are fully defined and working databases)?

1
2
10/5/2018 2:38:56 PM

Accepted Answer

If I understood you properly, you should implement the following:

1) Implement Service that will migrate your schema and seed data. (despite what they did in the latest version, I still prefer my implementation)

Helper

    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 Interface

internal interface ISeedService
{
    Task MigrateAsync();
    Task SeedAsync();
}

SeedService Implementation

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 file

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) Register context and related services in DI, which will allow dynamically retrieve connection string. There are several ways to do it, my implementation is not the best one, so it's up to you.

Startup.cs file

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 file.

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

I hope it help you.

2
10/5/2018 2:23:10 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow