Skip to content

EF Core 2.0: design-time DbContext discovery changes #258

Open
@divega

Description

@divega

There have been some changes made in 2.0 to the way EF Core discovers and creates your DbContext at design-time.

Please provide any feedback in the discussion thread at dotnet/efcore#9033.

Summary by @bricelam:

New way of getting application services

The recommended pattern for ASP.NET Core web applications has been updated for 2.0 in a way that broke the design-time logic EF Core used in 1.x. Previously at design-time, EF Core would try to invoke Startup.ConfigureServices directly in order to access the application's service provider. In ASP.NET Core 2.0, Configuration is initialized outside of the Startup class. Applications using EF Core typically access their connection string from Configuration, so Startup by itself is no longer sufficient. If you upgrade an ASP.NET Core 1.x application, you may receive the following error when using the EF Core tools.

No parameterless constructor was found on 'ApplicationContext'. Either add a parameterless constructor to 'ApplicationContext' or add an implementation of 'IDesignTimeDbContextFactory<ApplicationContext>' in the same assembly as 'ApplicationContext'

A new design-time hook has been added in ASP.NET Core 2.0. The static Program.BuildWebHost method enables EF Core to access the application's service provider at design time. If you are upgrading an ASP.NET Core 1.x application, you will need to update you Program class to resemble the following.

public class Program
{
    public static void Main(string[] args)
    {
        var host = BuildWebHost(args);

        host.Run();
    }

    // Tools will use this to get application services
    public static IWebHost BuildWebHost(string[] args) =>
        new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();
}

IDbContextFactory renamed

In order to support diverse application patterns and give users more control over how their DbContext is used at design time, we have, in the past, provided the IDbContextFactory<TContext> interface. At design-time, the EF Core tools will discover implementations of this interface in your project and use it to create DbContext objects.

This interface had a very general name which mislead some users to try re-using it for other DbContext-creating scenarios. They were caught off guard when the EF Tools then tried to use their implementation at design-time and caused commands like Update-Database or dotnet ef database update to fail.

In order to communicate the strong design-time semantics of this interface, we have renamed it to IDesignTimeDbContextFactory<TContext>.

For the 2.0 release the IDbContextFactory<TContext> still exists but is marked as obsolete.

DbContextFactoryOptions removed

Because of the ASP.NET Core 2.0 changes described above, we found that DbContextFactoryOptions was no longer needed on the new IDesignTimeDbContextFactory<TContext> interface. Here are the alternatives you should be using instead.

DbContextFactoryOptions Alternative
ApplicationBasePath AppContext.BaseDirectory
ContentRootPath Directory.GetCurrentDirectory()
EnvironmentName Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions