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.