Verwalten von Migrationen

Wenn sich Ihr Modell ändert, werden Migrationen als Teil der normalen Entwicklung hinzugefügt und entfernt, und die Migrationsdateien werden in die Quellcodeverwaltung Ihres Projekts eingecheckt. Zum Verwalten von Migrationen müssen Sie zuerst die EF Core-Befehlszeilentoolsinstallieren.

Tipp

Wenn sich DbContext in einer anderen Assembly als das Startprojekt befindet, können Sie die Ziel- und Startprojekte explizit in den Tools für die Paket-Manager-Konsole oder die .NET Core-CLI angeben.

Hinzufügen einer Migration

Nachdem Ihr Modell geändert wurde, können Sie eine Migration für diese Änderung hinzufügen:

dotnet ef migrations add AddBlogCreatedTimestamp

Der Migrationsname kann wie eine Commitnachricht in einem Versionskontrollsystem verwendet werden. Sie können beispielsweise einen Namen wie AddBlogCreatedTimestamp wählen, wenn es sich bei der Änderung um eine neue CreatedTimestamp-Eigenschaft für Ihre Blog-Entität handelt.

Drei Dateien werden Ihrem Projekt im Verzeichnis Migrationen hinzugefügt:

  • XXXXXXXXXXXXXX_AddCreatedTimestamp.cs – Die Hauptdatei der Migration. Enthält die Vorgänge, die zum Durchführen der Migration (in Up) und Rückgängigmachen (in Down) erforderlich sind.
  • XXXXXXXXXXXXXX_AddCreatedTimestamp.Designer.cs – Die Metadatendatei der Migration. Enthält Informationen, die vom EF verwendet werden.
  • MyContextModelSnapshot.cs – Eine Momentaufnahme des aktuellen Modells. Diese wird verwendet, um festzustellen, was sich beim Hinzufügen der nächsten Migration geändert hat.

Mit dem Zeitstempel im Dateinamen können Migrationen chronologisch angeordnet werden, sodass Sie den Fortschritt der Änderungen mitverfolgen können.

Namespaces

Es steht Ihnen frei, Migrationsdateien zu verschieben und ihren Namespace manuell zu ändern. Neue Migrationen werden als gleichgeordnete Elemente der letzten Migration erstellt. Alternativ können Sie das Verzeichnis zur Generierungszeit wie folgt angeben:

dotnet ef migrations add InitialCreate --output-dir Your/Directory

Hinweis

Sie können den Namespace auch unabhängig vom Verzeichnis mithilfe von --namespace ändern.

Anpassen des Migrationscodes

Obwohl EF Core in der Regel genaue Migrationen erstellt, sollten Sie den Code immer überprüfen und sicherstellen, dass er der gewünschten Änderung entspricht. In einigen Fällen ist dies sogar notwendig.

Spaltenumbenennungen

Ein bemerkenswertes Beispiel, bei dem das Anpassen von Migrationen erforderlich ist, ist die Umbenennung einer Eigenschaft. Wenn Sie beispielsweise eine Eigenschaft von Name in FullName umbenennen, wird EF Core die folgende Migration generieren:

migrationBuilder.DropColumn(
    name: "Name",
    table: "Customers");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customers",
    nullable: true);

EF Core kann in der Regel nicht wissen, wann die Absicht besteht, eine Spalte abzulegen und eine neue zu erstellen (zwei separate Änderungen), und wann eine Spalte umbenannt werden soll. Wenn die obige Migration unverändert angewendet wird, gehen alle Ihre Kundennamen verloren. Um eine Spalte umzubenennen, ersetzen Sie die oben generierte Migration durch Folgendes:

migrationBuilder.RenameColumn(
    name: "Name",
    table: "Customers",
    newName: "FullName");

Tipp

Der Einrüstvorgang der Migration warnt, wenn bei einem Vorgang Datenverlust eintreten kann (etwa beim Verwerfen einer Spalte). Wenn diese Warnung angezeigt wird, überprüfen Sie den Migrationscode besonders gründlich auf Genauigkeit.

Hinzufügen von unformatiertem SQL

Obwohl das Umbenennen einer Spalte über eine integrierte API erreicht werden kann, ist dies in vielen Fällen nicht möglich. Beispielsweise möchten wir vorhandene FirstName- und LastName-Eigenschaften durch eine einzelne, neue FullName-Eigenschaft ersetzen. Die von EF Core generierte Migration wird wie folgt aussehen:

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

Wie zuvor würde dies zu unerwünschtem Datenverlust führen. Um die Daten aus den alten Spalten zu übertragen, ordnen wir die Migrationen neu an und führen einen unformatierten SQL-Vorgang wie folgt ein:

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

migrationBuilder.Sql(
@"
    UPDATE Customer
    SET FullName = FirstName + ' ' + LastName;
");

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

Willkürliche Änderungen über unformatierte SQL

Unformatierte SQL kann auch zum Verwalten von Datenbankobjekten verwendet werden, die EF Core nicht kennt. Fügen Sie dazu eine Migration hinzu, ohne eine Modelländerung vorzunehmen. Es wird eine leere Migration generiert werden, die Sie dann mit unformatierten SQL-Vorgängen auffüllen können.

Die folgende Migration erstellt beispielsweise eine gespeicherte SQL Server-Prozedur:

migrationBuilder.Sql(
@"
    EXEC ('CREATE PROCEDURE getFullName
        @LastName nvarchar(50),
        @FirstName nvarchar(50)
    AS
        RETURN @LastName + @FirstName;')");

Tipp

EXEC wird verwendet, wenn eine Anweisung die erste oder einzige in einem SQL-Batch sein muss. Es kann auch verwendet werden, um Parserfehler in idempotenten Migrationsskripts zu umgehen, die auftreten können, wenn referenzierte Spalten in einer Tabelle derzeit nicht vorhanden sind.

Dies kann verwendet werden, um jeden Aspekt Ihrer Datenbank zu verwalten, einschließlich:

  • Gespeicherten Prozeduren
  • Volltextsuche
  • Funktionen
  • Auslöser
  • Ansichten

In den meisten Fällen umschließt EF Core bei der Anwendung von Migrationen automatisch jede Migration in ihre eigene Transaktion. Leider können einige Migrationsvorgänge in einigen Datenbanken nicht innerhalb einer Transaktion ausgeführt werden. In diesen Fällen können Sie die Transaktion verlassen, indem Sie suppressTransaction: true an migrationBuilder.Sql übergeben.

Entfernen einer Migration

Es kann vorkommen, dass Sie eine Migration hinzufügen und feststellen, dass Sie zusätzliche Änderungen an Ihrem EF Core-Modell vornehmen müssen, bevor Sie diese durchführen. Um die letzte Migration zu entfernen, verwenden Sie diesen Befehl.

dotnet ef migrations remove

Nachdem Sie die Migration entfernt haben, können Sie die zusätzlichen Modelländerungen vornehmen und sie erneut hinzufügen.

Warnung

Vermeiden Sie das Entfernen von Migrationen, die bereits auf Produktionsdatenbanken angewendet wurden. Dies würde bedeuten, dass Sie diese Migrationen nicht aus den Datenbanken wiederherstellen können und dass die Annahmen, die von nachfolgenden Migrationen gemacht werden, möglicherweise nicht mehr stimmen.

Auflisten von Migrationen

Sie können alle vorhandenen Migrationen wie folgt auflisten:

dotnet ef migrations list

Überprüfen auf ausstehende Modelländerungen

Hinweis

Dieses Feature wurde in EF Core 8.0 hinzugefügt.

Manchmal sollten Sie überprüfen, ob seit der letzten Migration Modelländerungen vorgenommen wurden. Dadurch können Sie feststellen, ob Sie oder ein Teammitglied vergessen haben, eine Migration hinzuzufügen. Eine Möglichkeit, dies zu erledigen, ist die Verwendung dieses Befehls.

dotnet ef migrations has-pending-model-changes

Sie können diese Überprüfung auch programmgesteuert mit context.Database.HasPendingModelChanges() ausführen. Diese Methode kann verwendet werden, um einen Komponententest zu schreiben, der fehlschlägt, wenn Sie vergessen, eine Migration hinzuzufügen.

Zurücksetzen aller Migrationen

In einigen extremen Fällen kann es notwendig sein, alle Migrationen zu entfernen und von vorn zu beginnen. Dies kann ganz einfach gemacht werden, indem Sie den Ordner Migrationen löschen und Ihre Datenbank trennen. An diesem Punkt können Sie eine neue Erstmigration erstellen, die Ihr gesamtes aktuelles Schema enthalten wird.

Es ist auch möglich, alle Migrationen zurückzusetzen und eine einzelne zu erstellen, ohne Ihre Daten zu verlieren. Dies wird manchmal als „Squashing“ bezeichnet und erfordert einige manuelle Arbeit:

  1. Sichern Sie Ihre Datenbank, falls ein Fehler auftritt.
  2. Löschen Sie in Ihrer Datenbank alle Zeilen aus der Migrationsverlaufstabelle (z. B. DELETE FROM [__EFMigrationsHistory] in SQL Server).
  3. Löschen Sie Ihren Ordner Migrationen.
  4. Erstellen Sie eine neue Migration, und generieren Sie ein SQL-Skript für diese (dotnet ef migrations script).
  5. Fügen Sie eine einzelne Zeile in den Migrationsverlauf ein, um aufzuzeichnen, dass die erste Migration bereits angewendet wurde, da Ihre Tabellen bereits vorhanden sind. Das Einfügen von SQL ist der letzte Vorgang im oben generierten SQL-Skript und funktioniert folgendermaßen (vergessen Sie nicht, die Werte zu aktualisieren):
INSERT INTO [__EFMigrationsHistory] ([MIGRATIONID], [PRODUCTVERSION])
VALUES (N'<full_migration_timestamp_and_name>', N'<EF_version>');

Warnung

Der gesamte benutzerdefinierte Migrationscode wird verloren gehen, wenn der Ordner Migrationen gelöscht wird. Alle Anpassungen müssen manuell auf die neue Erstmigration angewendet werden, damit sie erhalten bleiben.

Zusätzliche Ressourcen