DbContext-Lebensdauer, -Konfiguration und -InitialisierungDbContext Lifetime, Configuration, and Initialization

Dieser Artikel zeigt grundlegende Muster für die Initialisierung und Konfiguration einer DbContext-Instanz.This article shows basic patterns for initialization and configuration of a DbContext instance.

Die DbContext-LebensdauerThe DbContext lifetime

Die Lebensdauer eines DbContext beginnt mit dem Erstellen der Instanz und endet, wenn die Instanz verworfen wird.The lifetime of a DbContext begins when the instance is created and ends when the instance is disposed. Eine DbContext-Instanz ist für die Verwendung in einer einzelnen Arbeitseinheit konzipiert.A DbContext instance is designed to be used for a single unit-of-work. Dies bedeutet, dass die Lebensdauer einer DbContext-Instanz in der Regel sehr kurz ist.This means that the lifetime of a DbContext instance is usually very short.

Tipp

Um Martin Fowler aus dem Link oben zu zitieren: „Eine Arbeitseinheit verfolgt alle Aufgaben nach, die Sie während einer Geschäftstransaktion ausführen, die sich auf die Datenbank auswirken können.To quote Martin Fowler from the link above, "A Unit of Work keeps track of everything you do during a business transaction that can affect the database. Wenn Sie fertig sind, findet sie alles heraus, was getan werden muss, um die Datenbank als Ergebnis Ihrer Arbeit zu verändern“.When you're done, it figures out everything that needs to be done to alter the database as a result of your work."

Eine typische Arbeitseinheit bei Verwendung von Entity Framework Core (EF Core) umfasst Folgendes:A typical unit-of-work when using Entity Framework Core (EF Core) involves:

  • Erstellen einer DbContext-Instanz.Creation of a DbContext instance
  • Nachverfolgen von Entitätsinstanzen durch den Kontext.Tracking of entity instances by the context. Entitäten werden folgendermaßen nachverfolgt:Entities become tracked by
  • An den nachverfolgten Entitäten werden Änderungen vorgenommen, die für die Implementierung der Geschäftsregel erforderlich sind.Changes are made to the tracked entities as needed to implement the business rule
  • SaveChanges oder SaveChangesAsync wird aufgerufen.SaveChanges or SaveChangesAsync is called. EF Core erkennt die vorgenommenen Änderungen und schreibt sie in die Datenbank.EF Core detects the changes made and writes them to the database.
  • Die DbContext Instanz wird verworfen.The DbContext instance is disposed

Wichtig

  • Es ist sehr wichtig, DbContext nach der Verwendung zu verwerfen.It is very important to dispose the DbContext after use. Dadurch wird sichergestellt, dass alle nicht verwalteten Ressourcen freigegeben werden und dass die Registrierung für alle Ereignisse oder anderen Hooks aufgehoben wird, um Speicherverluste zu verhindern, falls die Instanz weiterhin referenziert wird.This ensures both that any unmanaged resources are freed, and that any events or other hooks are unregistered so as to prevent memory leaks in case the instance remains referenced.
  • DbContext ist nicht threadsicher.DbContext is not thread-safe. Geben Sie keine Kontexte zwischen Threads frei.Do not share contexts between threads. Stellen Sie sicher, dass await für alle asynchronen Aufrufe verwendet wird, bevor Sie die Kontextinstanz weiterhin verwenden.Make sure to await all async calls before continuing to use the context instance.
  • Eine InvalidOperationException, die von EF Core-Code ausgelöst wird, kann den Kontext in einen nicht wiederherstellbaren Zustand versetzen.An InvalidOperationException thrown by EF Core code can put the context into an unrecoverable state. Solche Ausnahmen weisen auf einen Programmfehler hin und sind nicht für Wiederherstellung konzipiert.Such exceptions indicate a program error and are not designed to be recovered from.

DbContext in Abhängigkeitsinjektion für ASP.NET CoreDbContext in dependency injection for ASP.NET Core

In vielen Webanwendungen entspricht jede HTTP-Anforderung einer einzelnen Arbeitseinheit.In many web applications, each HTTP request corresponds to a single unit-of-work. Dies bewirkt, dass das Anbinden der Kontextlebensdauer an die Anforderung für Webanwendungen eine gute Standardeinstellung ist.This makes tying the context lifetime to that of the request a good default for web applications.

ASP.NET Core-Anwendungen werden mithilfe von Abhängigkeitsinjektion konfiguriert.ASP.NET Core applications are configured using dependency injection. EF Core kann dieser Konfiguration mithilfe von AddDbContext in der ConfigurureServices-Methode von Startup.cs hinzugefügt werden.EF Core can be added to this configuration using AddDbContext in the ConfigurureServices method of Startup.cs. Beispiel:For example:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    
    services.AddDbContext<ApplicationDbContext>(
        options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));
}

In diesem Beispiel wird eine DbContext-Unterklasse mit dem Namen ApplicationDbContext als bereichsbezogener Dienst im ASP.NET Core-Anwendungsdienstanbieter registriert (auch alsThis example registers a DbContext subclass called ApplicationDbContext as a scoped service in the ASP.NET Core application service provider (a.k.a. Abhängigkeitsinjektionscontainer bezeichnet).the dependency injection container). Der Kontext ist so konfiguriert, dass der SQL Server-Datenbankanbieter verwendet und die Verbindungszeichenfolge aus der ASP.NET Core-Konfiguration gelesen wird.The context is configured to use the SQL Server database provider and will read the connection string from ASP.NET Core configuration. Es spielt in der Regel keine Rolle, wo in ConfigureServices der Aufruf von AddDbContext erfolgt.It typically does not matter where in ConfigureServices the call to AddDbContext is made.

Die ApplicationDbContext-Klasse muss einen öffentlichen Konstruktor mit einem Parameter DbContextOptions<ApplicationDbContext> bereitstellen.The ApplicationDbContext class must expose a public constructor with a DbContextOptions<ApplicationDbContext> parameter. Auf diese Weise wird die Kontextkonfiguration aus AddDbContext an DbContext übergeben.This is how context configuration from AddDbContext is passed to the DbContext. Beispiel:For example:

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

ApplicationDbContext kann dann mithilfe von Konstruktorinjektion in ASP.NET Core-Controllern oder anderen Diensten verwendet werden.ApplicationDbContext can then be used in ASP.NET Core controllers or other services through constructor injection. Beispiel:For example:

public class MyController
{
    private readonly ApplicationDbContext _context;

    public MyController(ApplicationDbContext context)
    {
        _context = context;
    }
}

Das Endergebnis ist eine ApplicationDbContext-Instanz, die für jede Anforderung erstellt und an den Controller zum Ausführen einer Arbeitseinheit übergeben wird, bevor sie verworfen wird, wenn die Anforderung beendet wird.The final result is an ApplicationDbContext instance created for each request and passed to the controller to perform a unit-of-work before being disposed when the request ends.

Weitere Informationen zu den Konfigurationsoptionen finden Sie weiter unten in diesem Artikel.Read further in this article to learn more about configuration options. Weitere Informationen zur Konfiguration und zu Abhängigkeitsinjektion in ASP.NET Core finden Sie unter App-Start in ASP.NET Core und Abhängigkeitsinjektion in ASP.NET Core.In addition, see App startup in ASP.NET Core and Dependency injection in ASP.NET Core for more information on configuration and dependency injection in ASP.NET Core.

Einfache DbContext-Initialisierung mit „new“Simple DbContext initialization with 'new'

DbContext-Instanzen können auf die normale .NET-Weise erstellt werden, z. B. mit new in C#.DbContext instances can be constructed in the normal .NET way, for example with new in C#. Die Konfiguration kann durch Überschreiben der OnConfiguring-Methode oder durch Übergeben von Optionen an den Konstruktor ausgeführt werden.Configuration can be performed by overriding the OnConfiguring method, or by passing options to the constructor. Beispiel:For example:

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test");
    }
}

Mit diesem Muster ist es auch einfach, Konfiguration wie etwa eine Verbindungszeichenfolge über den DbContext-Konstruktor zu übergeben.This pattern also makes it easy to pass configuration like the connection string via the DbContext constructor. Beispiel:For example:

public class ApplicationDbContext : DbContext
{
    private readonly string _connectionString;

    public ApplicationDbContext(string connectionString)
    {
        _connectionString = connectionString;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(_connectionString);
    }
}

Alternativ kann DbContextOptionsBuilder verwendet werden, um ein DbContextOptions-Objekt zu erstellen, das dann an den DbContext-Konstruktor übergeben wird.Alternately, DbContextOptionsBuilder can be used to create a DbContextOptions object that is then passed to the DbContext constructor. Dadurch kann ein DbContext, der für Abhängigkeitsinjektion konfiguriert ist, ebenfalls explizit erstellt werden.This allows a DbContext configured for dependency injection to also be constructed explicitly. Wenn Sie z. B. ApplicationDbContext verwenden, der für ASP.NET Core Web-Apps oben definiert ist:For example, when using ApplicationDbContext defined for ASP.NET Core web apps above:

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

DbContextOptions kann erstellt werden, und der Konstruktor kann explizit aufgerufen werden:The DbContextOptions can be created and the constructor can be called explicitly:

var contextOptions = new DbContextOptionsBuilder<ApplicationDbContext>()
    .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test")
    .Options;

using var context = new ApplicationDbContext(contextOptions);

Verwenden einer DbContext-Factory (z. B. für Blazor)Using a DbContext factory (e.g. for Blazor)

Einige Anwendungstypen (z. B. ASP.NET Core Blazor) verwenden Abhängigkeitsinjektion, erstellen aber keinen Dienstbereich, der der gewünschten DbContext-Lebensdauer entspricht.Some application types (e.g. ASP.NET Core Blazor) use dependency injection but do not create a service scope that aligns with the desired DbContext lifetime. Auch wenn eine solche Ausrichtung vorhanden ist, muss die Anwendung möglicherweise mehrere Arbeitseinheiten innerhalb dieses Bereichs ausführen.Even where such an alignment does exist, the application may need to perform multiple units-of-work within this scope. Beispielsweise mehrere Arbeitseinheiten innerhalb einer einzelnen HTTP-Anforderung.For example, multiple units-of-work within a single HTTP request.

In diesen Fällen kann AddDbContextFactory zum Registrieren einer Factory zum Erstellen von DbContext-Instanzen verwendet werden.In these cases, AddDbContextFactory can be used to register a factory for creation of DbContext instances. Beispiel:For example:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContextFactory<ApplicationDbContext>(options =>
        options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test"));
}

Die ApplicationDbContext-Klasse muss einen öffentlichen Konstruktor mit einem Parameter DbContextOptions<ApplicationDbContext> bereitstellen.The ApplicationDbContext class must expose a public constructor with a DbContextOptions<ApplicationDbContext> parameter. Dabei handelt es sich um dasselbe Muster, das im Abschnitt „Traditionelles ASP.NET Core“ weiter oben verwendet wird.This is the same pattern as used in the traditional ASP.NET Core section above.

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

Die DbContextFactory-Factory kann dann mithilfe von Konstruktorinjektion in anderen Diensten verwendet werden.The DbContextFactory factory can then be used in other services through constructor injection. Beispiel:For example:

private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;

public MyController(IDbContextFactory<ApplicationDbContext> contextFactory)
{
    _contextFactory = contextFactory;
}

Die injizierte Factory kann dann verwendet werden, um DbContext-Instanzen im Dienstcode zu erstellen.The injected factory can then be used to construct DbContext instances in the service code. Beispiel:For example:

public void DoSomething()
{
    using (var context = _contextFactory.CreateDbContext())
    {
        // ...
    }
}

Beachten Sie, dass die DbContext-Instanzen, die auf diese Weise erstellt werden, nicht vom Dienstanbieter der Anwendung verwaltet werden, weshalb diese von der Anwendung gelöscht werden müssen.Notice that the DbContext instances created in this way are not managed by the application's service provider and therefore must be disposed by the application.

Weitere Informationen zur Verwendung von EF Core mit Blazor finden Sie unter ASP.NET Core Blazor Server mit Entity Framework Core.See ASP.NET Core Blazor Server with Entity Framework Core for more information on using EF Core with Blazor.

DbContextOptionsDbContextOptions

Der Ausgangspunkt für die gesamte DbContext-Konfiguration ist DbContextOptionsBuilder.The starting point for all DbContext configuration is DbContextOptionsBuilder. Es gibt drei Möglichkeiten, diesen Generator abzurufen:There are three ways to get this builder:

  • In AddDbContext und verwandte MethodenIn AddDbContext and related methods
  • In OnConfiguringIn OnConfiguring
  • Explizit generiert mit newConstructed explicitly with new

Beispiele für jede dieser Möglichkeiten werden in den vorangehenden Abschnitten aufgeführt.Examples of each of these are shown in the preceding sections. Dieselbe Konfiguration kann unabhängig davon angewendet werden, wie der Generator abgerufen wurde.The same configuration can be applied regardless of where the builder comes from. Außerdem wird OnConfiguring immer unabhängig davon aufgerufen, wie der Kontext erstellt wird.In addition, OnConfiguring is always called regardless of how the context is constructed. Dies bedeutet, dass OnConfiguring selbst dann verwendet werden kann, um zusätzliche Konfigurationen auszuführen, wenn AddDbContext verwendet wird.This means OnConfiguring can be used to perform additional configuration even when AddDbContext is being used.

Konfigurieren des DatenbankanbietersConfiguring the database provider

Jede DbContext-Instanz muss so konfiguriert werden, dass sie nur einen Datenbankanbieter verwendet.Each DbContext instance must be configured to use one and only one database provider. (Verschiedene Instanzen eines DbContext-Untertyps können mit unterschiedlichen Datenbankanbietern verwendet werden, aber eine einzelne Instanz darf nur einen Datenbankanbieter verwenden.) Ein Datenbankanbieter wird mithilfe eines bestimmten Use*"-Aufrufs konfiguriert.(Different instances of a DbContext subtype can be used with different database providers, but a single instance must only use one.) A database provider is configured using a specific Use*" call. Wenn beispielsweise der SQL Server-Datenbankanbieter verwendet werden soll:For example, to use the SQL Server database provider:

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test");
    }
}

Diese Use*"-Methoden sind Erweiterungsmethoden, die vom Datenbankanbieter implementiert werden.These Use*" methods are extension methods implemented by the database provider. Dies bedeutet, dass das NuGet-Paket des Datenbankanbieters installiert werden muss, bevor die Erweiterungsmethode verwendet werden kann.This means that the database provider NuGet package must be installed before the extension method can be used.

Tipp

EF Core-Datenbankanbieter nutzen Erweiterungsmethoden ausgiebig.EF Core database providers make extensive use of extension methods. Wenn der Compiler angibt, dass eine Methode nicht gefunden werden kann, stellen Sie sicher, dass das NuGet-Paket des Anbieters installiert ist und dass Sie using Microsoft.EntityFrameworkCore; in Ihrem Code verwenden.If the compiler indicates that a method cannot be found, then make sure that the provider's NuGet package is installed and that you have using Microsoft.EntityFrameworkCore; in your code.

Die folgende Tabelle enthält Beispiele für gängige Datenbankanbieter.The following table contains examples for common database providers.

DatenbanksystemDatabase system BeispielkonfigurationExample configuration NuGet-PaketNuGet package
SQL Server oder Azure SQLSQL Server or Azure SQL .UseSqlServer(connectionString) Microsoft.EntityFrameworkCore.SqlServerMicrosoft.EntityFrameworkCore.SqlServer
Azure Cosmos DBAzure Cosmos DB .UseCosmos(connectionString, databaseName) Microsoft.EntityFrameworkCore.CosmosMicrosoft.EntityFrameworkCore.Cosmos
SQLiteSQLite .UseSqlite(connectionString) Microsoft.EntityFrameworkCore.SqliteMicrosoft.EntityFrameworkCore.Sqlite
EF Core-In-Memory-DatenbankEF Core in-memory database .UseInMemoryDatabase(databaseName) Microsoft.EntityFrameworkCore.InMemoryMicrosoft.EntityFrameworkCore.InMemory
PostgreSQL*PostgreSQL* .UseNpgsql(connectionString) Npgsql.EntityFrameworkCore.PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
MySQL/MariaDB*MySQL/MariaDB* .UseMySql((connectionString) Pomelo.EntityFrameworkCore.MySqlPomelo.EntityFrameworkCore.MySql
Oracle*Oracle* .UseOracle(connectionString) Oracle.EntityFrameworkCoreOracle.EntityFrameworkCore

*Diese Datenbankanbieter werden nicht von Microsoft ausgeliefert.*These database providers are not shipped by Microsoft. Weitere Informationen zu Datenbankanbietern finden Sie unter Datenbankanbieter.See Database Providers for more information about database providers.

Warnung

Die In-Memory-Datenbank von EF Core ist nicht für die Verwendung in der Produktion vorgesehen.The EF Core in-memory database is not designed for production use. Außerdem ist sie möglicherweise auch nicht die beste Wahl für Tests.In addition, it may not be the best choice even for testing. Weitere Informationen finden Sie unter Testen von Code, der EF Core verwendet.See Testing Code That Uses EF Core for more information.

Weitere Informationen zur Verwendung von Verbindungszeichenfolgen mit EF Core finden Sie unter Verbindungszeichenfolgen.See Connection Strings for more information on using connection strings with EF Core.

Eine für den Datenbankanbieter spezifische optionale Konfiguration wird in einem zusätzlichen anbieterspezifischen Generator ausgeführt.Optional configuration specific to the database provider is performed in an additional provider-specific builder. Verwenden Sie beispielsweise EnableRetryOnFailure, um Wiederholungsversuche für Verbindungsresilienz beim Herstellen einer Verbindung mit Azure SQL zu konfigurieren:For example, using EnableRetryOnFailure to configure retries for connection resiliency when connecting to Azure SQL:

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer(
                @"Server=(localdb)\mssqllocaldb;Database=Test",
                providerOptions =>
                    {
                        providerOptions.EnableRetryOnFailure();
                    });
    }
}

Tipp

Der gleiche Datenbankanbieter wird für SQL Server und Azure SQL verwendet.The same database provider is used for SQL Server and Azure SQL. Es wird jedoch empfohlen, beim Herstellen einer Verbindung mit SQL Azure Verbindungsresilienz zu verwenden.However, it is recommended that connection resiliency be used when connecting to SQL Azure.

Weitere Informationen zur anbieterspezifischen Konfiguration finden Sie unter Datenbankanbieter.See Database Providers for more information on provider-specific configuration.

Weitere DbContext-KonfigurationOther DbContext configuration

Weitere DbContext-Konfiguration kann vor oder nach dem Aufruf von Use* verkettet werden (dies macht keinen Unterschied).Other DbContext configuration can be chained either before or after (it makes no difference which) the Use* call. So aktivieren Sie z. B. Protokollierung sensibler Daten:For example, to turn on sensitive-data logging:

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .EnableSensitiveDataLogging()
            .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test");
    }
}

Die folgende Tabelle enthält Beispiele für gängige Methoden, die für DbContextOptionsBuilder aufgerufen werden.The following table contains examples of common methods called on DbContextOptionsBuilder.

DbContextOptionsBuilder-MethodeDbContextOptionsBuilder method FunktionsbeschreibungWhat it does Weitere InformationenLearn more
UseQueryTrackingBehavior Legt das Standardverhalten der Nachverfolgung für Abfragen fest.Sets the default tracking behavior for queries Verhalten der AbfragenachverfolgungQuery Tracking Behavior
LogTo Eine einfache Möglichkeit, EF Core-Protokolle zu erhalten (EF Core 5.0 oder höher).A simple way to get EF Core logs (EF Core 5.0 and later) Protokollierung, Ereignisse und DiagnoseLogging, Events, and Diagnostics
UseLoggerFactory Registriert eine Micrsofot.Extensions.Logging-Factory.Registers an Micrsofot.Extensions.Logging factory Protokollierung, Ereignisse und DiagnoseLogging, Events, and Diagnostics
EnableSensitiveDataLogging Schließt Anwendungsdaten in Ausnahmen und Protokollierung ein.Includes application data in exceptions and logging Protokollierung, Ereignisse und DiagnoseLogging, Events, and Diagnostics
EnableDetailedErrors Ausführlichere Abfragefehler (auf Kosten der Leistung).More detailed query errors (at the expense of performance) Protokollierung, Ereignisse und DiagnoseLogging, Events, and Diagnostics
ConfigureWarnings Ignoriert Warnungen und andere Ereignisse oder löst diese aus.Ignore or throw for warnings and other events Protokollierung, Ereignisse und DiagnoseLogging, Events, and Diagnostics
AddInterceptors Registriert EF Core-Interceptors.Registers EF Core interceptors Protokollierung, Ereignisse und DiagnoseLogging, Events, and Diagnostics
UseLazyLoadingProxies Verwendet dynamischer Proxys für verzögertes Laden.Use dynamic proxies for lazy-loading Verzögertes LadenLazy Loading
UseChangeTrackingProxies Verwendet dynamische Proxys für Änderungsnachverfolgung.Use dynamic proxies for change-tracking Bald verfügbar...Coming soon...

Hinweis

UseLazyLoadingProxies und UseChangeTrackingProxies sind Erweiterungsmethoden aus dem NuGet-Paket Microsoft.EntityFrameworkCore.Proxies.UseLazyLoadingProxies and UseChangeTrackingProxies are extension methods from the Microsoft.EntityFrameworkCore.Proxies NuGet package. Diese Art von „.UseSomething()“-Aufruf ist die empfohlene Methode zur Konfiguration und/oder Verwendung von EF Core-Erweiterungen, die in anderen Paketen enthalten sind.This kind of ".UseSomething()" call is the recommended way to configure and/or use EF Core extensions contained in other packages.

DbContextOptions und DbContextOptions<TContext> im VergleichDbContextOptions verses DbContextOptions<TContext>

Die meisten DbContext-Unterklassen, die DbContextOptions akzeptieren, sollten die generische DbContextOptions<TContext>-Variation verwenden.Most DbContext subclasses that accept a DbContextOptions should use the generic DbContextOptions<TContext> variation. Beispiel:For example:

public sealed class SealedApplicationDbContext : DbContext
{
    public SealedApplicationDbContext(DbContextOptions<SealedApplicationDbContext> contextOptions)
        : base(contextOptions)
    {
    }
}

Dadurch wird sichergestellt, dass die richtigen Optionen für den spezifischen DbContext-Untertyp aus der Abhängigkeitsinjektion aufgelöst werden, auch wenn mehrere DbContext-Untertypen registriert sind.This ensures that the correct options for the specific DbContext subtype are resolved from dependency injection, even when multiple DbContext subtypes are registered.

Tipp

Ihr DbContext muss nicht versiegelt sein, aber das Versiegeln ist eine bewährte Vorgehensweise für Klassen, die nicht für Vererbung entworfen wurden.Your DbContext does not need to be sealed, but sealing is best practice to do so for classes not designed to be inherited from.

Wenn jedoch vom DbContext-Untertyp selbst geerbt werden soll, sollte ein geschützter Konstruktor bereitgestellt werden, der generische DbContextOptions annimmt.However, if the DbContext subtype is itself intended to be inherited from, then it should expose a protected constructor taking a non-generic DbContextOptions. Beispiel:For example:

public abstract class ApplicationDbContextBase : DbContext
{
    protected ApplicationDbContextBase(DbContextOptions contextOptions)
        : base(contextOptions)
    {
    }
}

Dies ermöglicht es mehreren konkreten Unterklassen, diesen Basiskonstruktor mithilfe ihrer verschiedenen generischen DbContextOptions<TContext>-Instanzen aufzurufen.This allows multiple concrete subclasses to call this base constructor using their different generic DbContextOptions<TContext> instances. Beispiel:For example:

public sealed class ApplicationDbContext1 : ApplicationDbContextBase
{
    public ApplicationDbContext1(DbContextOptions<ApplicationDbContext1> contextOptions)
        : base(contextOptions)
    {
    }
}

public sealed class ApplicationDbContext2 : ApplicationDbContextBase
{
    public ApplicationDbContext2(DbContextOptions<ApplicationDbContext2> contextOptions)
        : base(contextOptions)
    {
    }
}

Beachten Sie, dass dies genau das gleiche Muster wie beim direkten Erben von DbContext ist.Notice that this is exactly the same pattern as when inheriting from DbContext directly. Das heißt, der DbContext-Konstruktor selbst akzeptiert aus diesem Grund nicht generische DbContextOptions.That is, the DbContext constructor itself accepts a non-generic DbContextOptions for this reason.

Eine DbContext-Unterklasse, die instanziiert und von der geerbt werden soll, sollte beide Formen des Konstruktors verfügbar machen.A DbContext subclass intended to be both instantiated and inherited from should expose both forms of constructor. Beispiel:For example:

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

    protected ApplicationDbContext(DbContextOptions contextOptions)
        : base(contextOptions)
    {
    }
}

DbContext-Konfiguration zur EntwurfszeitDesign-time DbContext configuration

EF Core-Entwurfszeittools (z. B. für EF Core-Migrationen) müssen in der Lage sein, eine funktionierende Instanz eines DbContext-Typs zu ermitteln und zu erstellen, um Details zu den Entitätstypen der Anwendung und deren Zuordnung zu einem Datenbankschema zu erfassen.EF Core design-time tools such as those for EF Core migrations need to be able to discover and create a working instance of a DbContext type in order to gather details about the application's entity types and how they map to a database schema. Dieser Prozess kann automatisch ausgeführt werden, solange das Tool die DbContext-Instanz problemlos so erstellen kann, dass sie ähnlich konfiguriert wird, wie sie zur Laufzeit konfiguriert würde.This process can be automatic as long as the tool can easily create the DbContext in such a way that it will be configured similarly to how it would be configured at run-time.

Obwohl jedes Muster, das die erforderlichen Konfigurationsinformationen für die DbContext-Instanz bereitstellt, zur Laufzeit funktionieren kann, können Tools, die die Verwendung einer DbContext-Instanz zur Entwurfszeit erfordern, nur mit einer begrenzten Anzahl von Mustern funktionieren.While any pattern that provides the necessary configuration information to the DbContext can work at run-time, tools that require using a DbContext at design-time can only work with a limited number of patterns. Diese werden unter Kontexterstellung zur Entwurfszeit ausführlicher behandelt.These are covered in more detail in Design-Time Context Creation.

Vermeiden von DbContext-ThreadingproblemenAvoiding DbContext threading issues

Entity Framework Core unterstützt nicht die Ausführung mehrerer paralleler Vorgänge, die für dieselbe DbContext-Instanz ausgeführt werden.Entity Framework Core does not support multiple parallel operations being run on the same DbContext instance. Dies schließt die parallele Ausführung von asynchronen Abfragen und jede explizite gleichzeitige Verwendung aus mehreren Threads ein.This includes both parallel execution of async queries and any explicit concurrent use from multiple threads. Verwenden Sie daher immer sofort asynchrone await-Aufrufe, oder verwenden Sie separate DbContext-Instanzen für Vorgänge, die parallel ausgeführt werden.Therefore, always await async calls immediately, or use separate DbContext instances for operations that execute in parallel.

Wenn EF Core den Versuch erkennt, eine DbContext-Instanz parallel zu verwenden, wird eine InvalidOperationException mit einer Meldung wie der folgenden angezeigt:When EF Core detects an attempt to use a DbContext instance concurrently, you'll see an InvalidOperationException with a message like this:

Ein zweiter Vorgang wurde für diesen Kontext gestartet, bevor ein vorheriger Vorgang abgeschlossen wurde.A second operation started on this context before a previous operation completed. Dies wird in der Regel durch verschiedene Threads verursacht, die dieselbe Instanz von DbContext verwenden, aber es ist nicht garantiert, dass Instanzmember threadsicher sind.This is usually caused by different threads using the same instance of DbContext, however instance members are not guaranteed to be thread safe.

Wenn gleichzeitiger Zugriff nicht erkannt wird, kann dies zu nicht definiertem Verhalten, Anwendungsabstürzen und Datenbeschädigung führen.When concurrent access goes undetected, it can result in undefined behavior, application crashes and data corruption.

Es gibt häufige Fehler, die versehentlich gleichzeitigen Zugriff auf dieselbe DbContext-Instanz verursachen können:There are common mistakes that can inadvertently cause concurrent access on the same DbContext instance:

Fehler bei asynchronen VorgängenAsynchronous operation pitfalls

Asynchrone Methoden ermöglichen EF Core das Initiieren von Vorgängen, die auf nicht blockierende Weise auf die Datenbank zugreifen.Asynchronous methods enable EF Core to initiate operations that access the database in a non-blocking way. Wenn ein Aufrufer jedoch nicht auf den Abschluss einer dieser Methoden wartet und andere Vorgänge für DbContext ausführt, kann der Status von DbContext beschädigt sein (und ist es sehr wahrscheinlich auch).But if a caller does not await the completion of one of these methods, and proceeds to perform other operations on the DbContext, the state of the DbContext can be, (and very likely will be) corrupted.

Warten Sie immer sofort auf asynchrone EF Core-Methoden.Always await EF Core asynchronous methods immediately.

Implizites Freigeben von DbContext-Instanzen über AbhängigkeitsinjektionImplicitly sharing DbContext instances via dependency injection

Die AddDbContext-Erweiterungsmethode registriert standardmäßig DbContext-Typen mit einer begrenzten Lebensdauer.The AddDbContext extension method registers DbContext types with a scoped lifetime by default.

Dies vermeidet in den meisten ASP.NET Core-Anwendungen Probleme durch gleichzeitigen Zugriff, weil es nur einen Thread gibt, der jede Clientanforderung zu einer bestimmten Zeit ausführt, und weil jede Anforderung einen separaten Abhängigkeitsinjektionsbereich (und damit eine separate DbContext-Instanz) erhält.This is safe from concurrent access issues in most ASP.NET Core applications because there is only one thread executing each client request at a given time, and because each request gets a separate dependency injection scope (and therefore a separate DbContext instance). Für das Blazor Server-Hostingmodell wird eine logische Anforderung zum Verwalten der Blazor-Benutzerverbindung verwendet. Daher ist nur eine bereichsbezogene DbContext-Instanz pro Benutzerverbindung verfügbar, wenn der standardmäßige Injektionsbereich verwendet wird.For Blazor Server hosting model, one logical request is used for maintaining the Blazor user circuit, and thus only one scoped DbContext instance is available per user circuit if the default injection scope is used.

Jeder Code, der explizit mehrere Threads parallel ausführt, sollte sicherstellen, dass auf DbContext-Instanzen niemals gleichzeitig zugegriffen wird.Any code that explicitly executes multiple threads in parallel should ensure that DbContext instances aren't ever accessed concurrently.

Mithilfe von Abhängigkeitsinjektion kann dies erreicht werden, indem der Kontext als bereichsbezogen registriert wird und Bereiche (mit IServiceScopeFactory) für jeden Thread erstellt werden, oder indem DbContext als vorübergehender Wert registriert wird (mithilfe der Überladung von AddDbContext, die einen ServiceLifetime-Parameter annimmt).Using dependency injection, this can be achieved by either registering the context as scoped, and creating scopes (using IServiceScopeFactory) for each thread, or by registering the DbContext as transient (using the overload of AddDbContext which takes a ServiceLifetime parameter).

Weitere InformationenMore reading