Codebasierte Konfigurationen

Hinweis

Nur EF6 und höher: Die Features, APIs usw., die auf dieser Seite erläutert werden, wurden in Entity Framework 6 eingeführt. Wenn Sie eine frühere Version verwenden, gelten manche Informationen nicht.

Die Konfiguration für eine Entity Framework-Anwendung kann in einer Konfigurationsdatei („app.config/web.config“) oder über Code angegeben werden. Letzteres wird als codebasierte Konfiguration bezeichnet.

Die Konfiguration in einer Konfigurationsdatei wird in einem separaten Artikelbeschrieben. Die Konfigurationsdatei hat Vorrang vor der codebasierten Konfiguration. Anders ausgedrückt: Wenn eine Konfigurationsoption sowohl im Code als auch in der Konfigurationsdatei festgelegt wird, wird die Einstellung in der Konfigurationsdatei verwendet.

Verwenden von DbConfiguration

Die codebasierte Konfiguration wird in EF 6 und höher durch Erstellen einer Unterklasse von System.Data.Entity.Config.DbConfiguration erreicht. Die folgenden Richtlinien sollten beim Erstellen von Unterklassen von DbConfiguration beachtet werden:

  • Erstellen Sie nur eine DbConfiguration-Klasse für Ihre Anwendung. Diese Klasse gibt Einstellungen an, die für die gesamte App-Domäne gelten.
  • Platzieren Sie die DbConfiguration-Klasse in derselben Assembly wie die DbContext-Klasse. (Wenn Sie dies ändern möchten, lesen Sie den Abschnitt Verschieben von DbConfiguration.)
  • Geben Sie Ihrer DbConfiguration-Klasse einen öffentlichen Konstruktor ohne Parameter.
  • Legen Sie Konfigurationsoptionen fest, indem Sie geschützte DbConfiguration-Methoden aus diesem Konstruktor aufrufen.

Mit diesen Richtlinien kann EF Ihre Konfiguration automatisch ermitteln und verwenden, wenn Tools auf Ihr Modell zugreifen müssen und wenn die Anwendung ausgeführt wird.

Beispiel

Eine von DbConfiguration abgeleitete Klasse könnte wie folgt aussehen:

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.SqlServer;

namespace MyNamespace
{
    public class MyConfiguration : DbConfiguration
    {
        public MyConfiguration()
        {
            SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
            SetDefaultConnectionFactory(new LocalDbConnectionFactory("mssqllocaldb"));
        }
    }
}

Diese Klasse richtet EF so ein, dass die SQL Azure-Ausführungsstrategie verwendet wird, um fehlerhafte Datenbankvorgänge automatisch erneut zu wiederholen, und dass Datenbanken, die per Konvention durch Code First erstellt werden, lokal verwendet werden.

Verschieben von DbConfiguration

In einigen Fällen ist es nicht möglich, Ihre DbConfiguration-Klasse in derselben Assembly wie die DbContext-Klasse zu platzieren. Beispielsweise verfügen Sie möglicherweise über zwei DbContext-Klassen in verschiedenen Assemblys. Es gibt zwei Optionen für den Umgang damit.

Die erste Option besteht darin, die Konfigurationsdatei zum Angeben der zu verwendenden DbConfiguration-Instanz zu verwenden. Legen Sie dazu das codeConfigurationType-Attribut im Abschnitt „entityFramework“ fest. Beispiel:

<entityFramework codeConfigurationType="MyNamespace.MyDbConfiguration, MyAssembly">
    ...Your EF config...
</entityFramework>

Der Wert von codeConfigurationType muss der qualifizierte Name Ihrer DbConfiguration-Klasse für die Assembly und den Namespace sein.

Die zweite Option besteht darin, DbConfigurationTypeAttribute in Ihrer Kontextklasse zu platzieren. Beispiel:

[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}

Der an das Attribut übergebene Wert kann entweder Ihr DbConfiguration-Typ (wie oben dargestellt) oder die Zeichenfolge des qualifizierten Typnamens für die Assembly und den Namespace sein. Beispiel:

[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")]
public class MyContextContext : DbContext
{
}

Explizites Festlegen von DbConfiguration

Es gibt einige Situationen, in denen eine Konfiguration erforderlich sein kann, bevor der DbContext-Typ verwendet wurde. Beispiele hierfür sind:

  • Verwenden von DbModelBuilder zum Erstellen eines Modells ohne Kontext
  • Verwenden von Code für ein anderes Framework/Hilfsprogramm, der einen DbContext nutzt, in dem dieser Kontext vor dem Anwendungskontext verwendet wird

In solchen Situationen kann EF die Konfiguration nicht automatisch ermitteln, und Sie müssen stattdessen eine der folgenden Aktionen ausführen:

  • Festlegen des DbConfiguration-Typs in der Konfigurationsdatei fest, wie im Abschnitt Verschieben von DbConfiguration oben beschrieben
  • Aufrufen der statischen DbConfiguration.SetConfiguration-Methode beim Starten der Anwendung

Außerkraftsetzen von DbConfiguration

Es gibt einige Situationen, in denen Sie die in der DbConfiguration festgelegte Konfiguration außer Kraft setzen müssen. Dies geschieht in der Regel nicht durch Anwendungsentwickler*innen, sondern durch Drittanbieter und Plug-Ins, die keine abgeleitete DbConfiguration-Klasse verwenden können.

Daher ermöglicht EntityFramework das Registrieren eines Ereignishandlers, der die vorhandene Konfiguration direkt vor dem Sperren ändern kann. Außerdem wird zur Vereinfachung eine Methode speziell für den Austausch von Diensten, die vom EF-Dienstlocator zurückgegeben werden, bereitgestellt. Diese Methode soll folgendermaßen verwendet werden:

  • Beim Starten der App (bevor EF verwendet wird) sollte das Plug-In oder der Anbieter die Ereignishandlermethode für dieses Ereignis registrieren. (Beachten Sie, dass dies vor der Verwendung von EF durch die Anwendung geschehen muss.)
  • Der Ereignishandler ruft dann für jeden Dienst, der ersetzt werden muss, ReplaceService auf.

Um z. B. IDbConnectionFactory und DbProviderService zu ersetzen, registrieren Sie einen Handler etwa wie folgt:

DbConfiguration.Loaded += (_, a) =>
   {
       a.ReplaceService<DbProviderServices>((s, k) => new MyProviderServices(s));
       a.ReplaceService<IDbConnectionFactory>((s, k) => new MyConnectionFactory(s));
   };

Im obigen Code stellen MyProviderServices und MyConnectionFactory Ihre Implementierungen des Diensts dar.

Sie können auch zusätzliche Abhängigkeitshandler hinzufügen, um denselben Effekt zu erzielen.

Beachten Sie, dass Sie auch DbProviderFactory auf diese Weise umschließen können, dies wirkt sich jedoch nur auf EF aus und nicht auf die Verwendung der DbProviderFactory außerhalb von EF. Aus diesem Grund sollten Sie wahrscheinlich weiterhin DbProviderFactory wie zuvor umschließen.

Sie sollten auch die Dienste berücksichtigen, die Sie außerhalb Ihrer Anwendung ausführen, z. B. beim Ausführen von Migrationen aus der Paket-Manager-Konsole. Wenn Sie die Migration über die Konsole ausführen, wird versucht, Ihre DbConfiguration zu finden. Ob der umschlossene Dienst abgerufen wird, hängt jedoch davon ab, wo der Ereignishandler registriert wurde. Wenn sie als Teil der Konstruktion Ihrer DbConfiguration registriert wurde, sollte der Code ausgeführt und der Dienst umschlossen werden. In der Regel ist dies nicht der Fall, sodass die Tools den umschlossenen Dienst nicht erhalten.