EF Core 2.0 Migrations without Hard-Coded Connection Strings

December 19, 2017
Cover Image

Earlier this year, I blogged about how to do EF Core migrations without hard-coding your connection string.  The short answer was to use IDbContextFactory.  Well, that was Entity Framework Core 1.0 and now we're on Entity Framework Core 2.0 and that IDbContextFactory interface went away.

So how to do you do EF Core 2.0 migrations without hard-coding your connection string?  The answer is the new IDesignTimeDbContextFactory interface...but just to keep life interesting, this interface does not appear in the documentation for EF Core 2.0.  (shrug)

I've created a sample implementation of IDesignTimeDbContextFactory that you can use in your project for your EF Core DbContext classes.  I had a couple of goals with this:

  1. Read connection strings from appsettings.json
  2. Use the ASPNETCORE_ENVIRONMENT environment variable so that I can do environment-specific connection string settings using appsettings..json
  3. Allow me to override connection strings that are in appsettings.json or appsettings..json by specifying connection strings as an environment variable
  4. Minimize duplicate code

The implementation that I came up with is an abstract class named DesignTimeDbContextFactoryBase.

It implements IDesignTimeDbContextFactory's CreateDbContext(string[]) method and also has all the other logic for dealing with SQL Server, appsettings.json, and the environment variables.  Since this is an abstract class, you'll need to create your own implementation but that implementation is going to consist of probably less than 10 lines of code.  There's only one method that needs to be implemented and it only has to be there because C# generics don't let you (easily) specify how to address a constructor on a derived generic class.  That method is CreateNewInstance() and you simply have to return an instance of your DbContext class using the appropriate constructor.

The code below shows you what your implementation will look like for a DbContext class named MyDbContext.

public class MyDbContextDesignTimeDbContextFactory :
        DesignTimeDbContextFactoryBase<MyDbContext>
{
    protected override MyDbContext CreateNewInstance(
        DbContextOptions<MyDbContext> options)
    {
        return new MyDbContext(options);
    }        
}

Here is a link for just the code for the DesignTimeDbContextFactoryBase classes.

Here's a link to some sample application code.

I hope this helps.

-Ben

-- Looking for help with Entity Framework and Entity Framework Core?  Not sure what your EF Core software architecture should be?  Want some training on EF Core or EF Core DevOps?  We can help.  Drop us a line at info@benday.com.