Search code examples
asp.net-coreentity-framework-coreasp.net-core-webapientity-framework-core-migrations

Migration with two different connection strings in Entity Framework


I have one DbContext and two databases, one for debugging / development (local) and one for production (online). I switch them with the appsetting.Development.json and appsettings.Production.json files.

Both just look like this:

{
  "ConnectionStrings": {
    "Default": "Server={myServer};Persist Security Info=False;User ID={MyUser};Password={myPassword};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
  }

So when I work on the Code and start it, it uses the localDb and when I publish it, it uses the other db.

Now when I change something in my Models I have always to delete the migration files, then do

dotnet ef migrations add InitialModel

and then

dotnet ef database update

after that delete the migrations file again, change the appsettings.Development.json entry to my online db and do the commands again.

So here are my questions:

  1. Is there a way to choose what config should be used in the migration commands? Like:

     dotnet ef migrations add InitialModel --config Production
    
  2. Is there a way to use the Migration Files with both databases so that I don't have to delete the migration files always?


Solution

  • I am not sure if there is a Migration command that let's you choose config seeing as the connection string is added in the Startup.cs file. However, I can share how i do it and you see if it works for you. Normally, i would have two connection strings in the appsettings.json file. Something like this "ConnectionStrings": {"DevConnection": "Data source=databasename.db","ProdConnection":"Data source=databasename.db"}, and in the Startup.cs file, i specify the connection string in the dependency injection container. In my Program.cs file, i have this

            var host = CreateHostBuilder(args).Build();
            using(var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var context = services.GetRequiredService<DataContext>();
                    var userManager = services.GetRequiredService<UserManager<AppUser>>(); //if you have users in your seed data
                    context.Database.Migrate();
                    Seed.SeedData(context, userManager).Wait(); //If you have seed data with test users
    
                }
                catch(Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred during migration");
                }
            }
            host.Run();
    

    This piece of code ensures you don't need to run the Update database command. You just create your migration and start your application. What you just need to do is after development, you switch the connection string in the Dependency Injection container. You don't need to run the Update Database command when you switch the connection string. You can also use Environment Variables. You can have a look at that and see how it works.