3
votes

Previously i had to implement IDesignTimeDbContextFactory to get migrations running, e.g: PM > Add-Migration Initial PM > Update-Database

If not, the console threw an error and led me here: https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext#use-idesigntimedbcontextfactory.

So i did what it suggested and got migrations running. After that i have created new projects, and i didn't have to implement the IDesignTimeDbContextFactory. Migrations worked anyway. How is this possible? Same .NET Core version (2.0) on all of the projects.

Do we always need to create a IDesignTimeDbContextFactory, or is it just in certain situations?

Thanks!

2
Might be thanks, i found the discussion on github so i'll post the question there as well and get back when i've gotten a response.Jan Banan

2 Answers

4
votes

Okay, here it goes: If you have a default constructor in your DbContext or are using the Program.BuildWebHost() pattern established in the ASP.NET Core 2.0 project templates, you typically won't need an IDesignTimeDbContextFactory implementation.

In 2.0.0-preview1 Program.BuildWebHost() wasn't used and you needed a design-time factory.

See this thread for full discussion: https://github.com/aspnet/EntityFrameworkCore/issues/9033

1
votes

As Dan Banan stated, if a DbContext has a default constructor, it won't need an IDesignTimeDbContextFactory at design time. However, if it needs to be configured from Startup, it will need a constructor which takes accepts DbContextOptions<T> and invokes the corresponding base constructor. However, this will create another issue. The DbContext's OnConfigure method will be called regardless of which constructor is used.

To account for these details, I've found the following pattern to be useful:

DbContext Configuration and Dependency Injection

serviceCollection
    .AddDbContext<MyDbContext>(
        options => options.UseSqlServer(configuration.GetConnectionString("MyDb"),
        ServiceLifetime.Transient
    );

MyDbContext.cs

public class MyDbContext : DbContext
{
    public SureshotDbContext()
    {
        // This allows for instantiation at design time.
    }

    public MyDbContext(DbContextOptions<MyDbContext> options) :
        base(options)
    {
        // This allows for configuration in real applications.
    }

    protected override void OnConfiguring(
        DbContextOptionsBuilder optionsBuilder
    )
    {
        if (optionsBuilder.IsConfigured)
        {
            return;
        }

        optionsBuilder.UseSqlServer(nameof(TDbContext));
    }
}