DbContext-Instanzerstellung zur Entwurfszeit

Einige der EF Core-Toolbefehle (z. B. die Migrationsbefehle) erfordern die Erstellung einer abgeleiteten DbContext-Instanz zur Entwurfszeit, um Details zu den Entitätstypen der Anwendung und deren Zuordnung zu einem Datenbankschema zu sammeln. In den meisten Fällen ist es wünschenswert, dass der so erstellte DbContext auf ähnliche Weise konfiguriert wird, wie wenn er zur Laufzeit konfiguriert würde.

Es gibt verschiedene Möglichkeiten, wie die Tools versuchen, den DbContext zu erstellen:

Aus Anwendungsdiensten

Wenn Ihr Startprojekt den ASP.NET Core-Webhost oder den generischen .NET Core-Host verwendet, versuchen die Tools, das DbContext-Objekt vom Dienstanbieter der Anwendung zu erhalten.

Die Tools versuchen zunächst, den Dienstanbieter zu erhalten, indem sie Program.CreateHostBuilder() aufrufen, Build() aufrufen und dann auf die Services-Eigenschaft zugreifen.

public class Program
{
    public static void Main(string[] args)
        => CreateHostBuilder(args).Build().Run();

    // EF Core uses this method at design time to access the DbContext
    public static IHostBuilder CreateHostBuilder(string[] args)
        => Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(
                webBuilder => webBuilder.UseStartup<Startup>());
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
        => services.AddDbContext<ApplicationDbContext>();

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
}

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

Hinweis

Wenn Sie eine neue ASP.NET Core-Anwendung erstellen, ist dieser Hook standardmäßig enthalten.

Der DbContext selber und alle Abhängigkeiten in seinem Konstruktor müssen als Dienste im Dienstanbieter der Anwendung registriert werden. Dies kann ganz einfach mit einem Konstruktor für DbContext erreicht werden, der eine Instanz von DbContextOptions<TContext> als Argument annimmt und die AddDbContext<TContext>-Methode verwendet.

Verwenden eines Konstruktors ohne Parameter

Wenn der DbContext nicht vom Anwendungsdienstanbieter abgerufen werden kann, suchen die Tools nach dem abgeleiteten DbContext-Typ innerhalb des Projekts. Anschließend versuchen sie, eine Instanz mit einem Konstruktor ohne Parameter zu erstellen. Dies kann der Standardkonstruktor sein, wenn der DbContext mithilfe der OnConfiguring-Methode konfiguriert wird.

Von einer Entwurfszeit-Factory

Sie können auch den Tools mitteilen, wie sie Ihren DbContext erstellen sollen, indem Sie die Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory<TContext>-Schnittstelle implementieren: Wenn eine Klasse, die diese Schnittstelle implementiert, entweder in demselben Projekt wie das abgeleitete DbContext oder im Startprojekt der Anwendung gefunden wird, umgehen die Tools die anderen Methoden zum Erstellen von DbContext und verwenden stattdessen die Entwurfszeit-Factory.

public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
{
    public BloggingContext CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
        optionsBuilder.UseSqlite("Data Source=blog.db");

        return new BloggingContext(optionsBuilder.Options);
    }
}

Eine Entwurfszeit-Factory kann besonders nützlich sein, wenn Sie die Entwurfszeit für DbContext anders konfigurieren müssen als zur Laufzeit, wenn der DbContext-Konstruktor zusätzliche Parameter verwendet, nicht in DI registriert ist, wenn Sie DI überhaupt nicht verwenden, oder wenn Sie aus irgendeinem Grund lieber keine CreateHostBuilder-Methode in der Main-Klasse Ihrer ASP.NET Core-Anwendung verwenden möchten.

Args

Sowohl IDesignTimeDbContextFactory<TContext>.CreateDbContext las auch Program.CreateHostBuilder akzeptieren Befehlszeilenargumente.

Sie können diese Argumente aus den Tools spezifizieren:

dotnet ef database update -- --environment Production

Das ---Token weist dotnet ef an, alles nachfolgende als Argument zu behandeln und nicht zu versuchen, es als Optionen zu parsen. Alle zusätzlichen Argumente, die von dotnet ef nicht verwendet werden, werden an die App weitergeleitet.