Rollback von Entity Framework und Entfernen fehlerhafter Migration

174

Ich verwende EF 6.0 für mein Projekt in C # mit manuellen Migrationen und Updates. Ich habe ungefähr 5 Migrationen in der Datenbank, aber ich habe festgestellt, dass die letzte Migration schlecht war und ich sie nicht will. Ich weiß, dass ich auf eine vorherige Migration zurücksetzen kann, aber wenn ich eine neue (feste) Migration hinzufüge und Update-Database ausführe, wird sogar die fehlerhafte Migration angewendet.

Ich habe versucht, ein Rollback auf die vorherige Migration durchzuführen und die Datei mit einer fehlerhaften Migration zu löschen. Wenn ich dann versuche, eine neue Migration hinzuzufügen, wird beim Aktualisieren der Datenbank eine Fehlermeldung angezeigt, da die Migrationsdatei beschädigt ist (genauer gesagt, die erste Codezeile benennt die Tabelle A in B um und ist die nächste Zeile, mit der EF versucht, die Tabelle zu aktualisieren Name A - vielleicht ist es ein EF-Fehler).

Gibt es eine Abfrage, die ich ausführen kann und die EF so etwas wie "Vergiss die letzte Migration, als ob sie nie existiert hätte, sie war schlecht" mitteilen würde? So etwas wie Remove-Migration.

Edit1 Ich habe eine für mich geeignete Lösung gefunden. Modell in den guten Zustand ändern und ausführen Add-Migration TheBadMigration -Force. Dadurch wird die letzte, nicht angewendete Migration neu aufgebaut.

Auf jeden Fall beantwortet dies die ursprüngliche Frage immer noch nicht vollständig. Wenn ich die Datenbank auf die fehlerhafte Migration aktualisiere, habe ich keine gute Möglichkeit gefunden, ein Rollback durchzuführen und eine neue Migration zu erstellen, mit Ausnahme der fehlerhaften.

Vielen Dank

Martin Brabec
quelle
Ich musste Visual Studio neu starten und dann fing es richtig an zu funktionieren. Das ist mir schon ein paar Mal passiert, immer nachdem ich mit Migrationen herumgespielt habe, ohne die Datenbank tatsächlich zu aktualisieren, also ist dort etwas Seltsames mit den Werkzeugen los.
Andrei Dvoynos

Antworten:

167

Sie haben 2 Möglichkeiten:

  • Sie können den Down aus der fehlerhaften Migration entfernen und in eine neue Migration einfügen (Sie müssen auch die nachfolgenden Änderungen am Modell vornehmen). Dies führt effektiv zu einer besseren Version.

    Ich verwende diese Option für Dinge, die in mehrere Umgebungen gegangen sind.

  • Die andere Option besteht darin, tatsächlich Update-Database –TargetMigration: TheLastGoodMigrationfür Ihre bereitgestellte Datenbank zu arbeiten und dann die Migration aus Ihrer Lösung zu löschen. Dies ist eine Art Hulk-Smash-Alternative und erfordert, dass dies für jede Datenbank durchgeführt wird, die mit der fehlerhaften Version bereitgestellt wird.

    Hinweis: Um die Migration erneut zu erstellen, können Sie sie verwenden Add-Migration [existingname] -Force. Dadurch wird jedoch Ihre vorhandene Migration überschrieben. Tun Sie dies daher nur, wenn Sie die vorhandene Migration aus der Datenbank entfernt haben. Dies entspricht dem Löschen der vorhandenen Migrationsdatei und dem Ausführenadd-migration

    Ich benutze diese Option während der Entwicklung.

Nicht geliebt
quelle
1
Die Hulk-Smash-Option funktioniert nicht. Ich habe die fehlerhafte Migration noch nicht auf die Datenbank angewendet. Ich habe es versucht, aber es hat nicht funktioniert, weil die Tabellennamen, die ich in der ursprünglichen Frage angegeben habe. Die erste Option gefällt mir nicht besonders, da ich anscheinend den Code der Migration ändern müsste. Wenn ich es schlecht mache, kann ich alles kaputt machen.
Martin Brabec
8
Wenn Sie die fehlerhafte Migration noch nicht angewendet haben, hindert Sie nichts daran, sie zu löschen und die fehlerhafte Migration neu zu erstellen oder zu korrigieren.
Nicht geliebt
4
Der 'Hulk Smash' ist die Antwort, er funktioniert bei der Entwicklung und ich möchte der verpassten Migration etwas hinzufügen. Ich denke, die Gründe, warum es für Martin nicht funktioniert hat, hängen nicht zusammen (oder hängen wahrscheinlich damit zusammen, dass das Datenbankschema manuell
geändert
1
@ BenRethmeier Als allgemeine Regel verwende ich die Hulk-Smash-Option nur während der Entwicklung. In prod erstelle ich immer eine neue Migration, um das Problem zu beheben. Der Grund ist, dass Sie einen manuellen Eingriff benötigen, wenn Sie die Datenbank herunterstufen. Ich mag nichts, was manuelles Eingreifen in das Produkt erfordert.
Nicht geliebt
1
HULK SMASH !!!! --- Ich habe versucht, nett zu sein, aber EF hat nicht abgespielt - ich bin zum letzten bekannten zurückgekehrt - (gesicherte Migrationsdateien) Gelöscht, Migration hinzugefügt - Erzwingen - In vorherige umbenannt und den Code kopiert. Datenbank aktualisieren und dann hinzufügen die zweite Migration auf die gleiche Weise - keine Fehler - wieder normal
Traci
127

Wie aus der Frage hervorgeht, gilt dies für eine Migration in einer Entwicklungstypumgebung, die noch nicht freigegeben wurde.

Dieses Problem kann in den folgenden Schritten behoben werden: Stellen Sie Ihre Datenbank auf die letzte gute Migration zurück, löschen Sie die schlechte Migration aus Ihrem Entity Framework-Projekt, generieren Sie eine neue Migration und wenden Sie sie auf die Datenbank an. Hinweis: Nach den Kommentaren zu urteilen, sind diese genauen Befehle möglicherweise nicht mehr anwendbar, wenn Sie EF Core verwenden.

Schritt 1: Wiederherstellen einer vorherigen Migration

Wenn Sie Ihre Migration noch nicht angewendet haben, können Sie diesen Teil überspringen. Um Ihr Datenbankschema auf einen früheren Punkt zurückzusetzen, geben Sie mit dem Befehl Update-Database mit der Option -TargetMigration die letzte gute Migration an. Wenn sich Ihr Entity-Framework-Code in einem anderen Projekt in Ihrer Lösung befindet, müssen Sie möglicherweise die Option '-Project' verwenden oder das Standardprojekt in der Paketmanager-Konsole wechseln.

Update-Database TargetMigration: <name of last good migration>

Um den Namen der letzten guten Migration abzurufen, rufen Sie mit dem Befehl 'Get-Migrations' eine Liste der Migrationsnamen ab, die auf Ihre Datenbank angewendet wurden.

PM> Get-Migrations
Retrieving migrations that have been applied to the target database.
201508242303096_Bad_Migration
201508211842590_The_Migration_applied_before_it
201508211440252_And_another

Diese Liste zeigt zuerst die zuletzt angewendeten Migrationen. Wählen Sie die Migration aus, die in der Liste nach der Migration erfolgt, auf die Sie ein Downgrade durchführen möchten, dh die Migration, die vor der Migration angewendet wurde, auf die Sie ein Downgrade durchführen möchten. Stellen Sie nun eine Update-Datenbank aus.

Update-Database TargetMigration: "<the migration applied before it>"

Alle nach der angegebenen Migration angewendeten Migrationen werden herabgestuft, um mit der zuletzt zuerst angewendeten Migration zu beginnen.

Schritt 2: Löschen Sie Ihre Migration aus dem Projekt

remove-migration name_of_bad_migration

Wenn der remove-migrationBefehl in Ihrer Version von Entity Framework nicht verfügbar ist, löschen Sie die Dateien der unerwünschten Migration Ihres EF-Projektordners "Migrationen" manuell. Zu diesem Zeitpunkt können Sie eine neue Migration erstellen und auf die Datenbank anwenden.

Schritt 3: Fügen Sie Ihre neue Migration hinzu

add-migration my_new_migration

Schritt 4: Wenden Sie Ihre Migration auf die Datenbank an

update-database
David Sopko
quelle
6
Mit EF Core scheint Get-Migrations entfernt worden zu sein.
Kevin Burton
1
Schritt 2 ! - Sehr nützliche Funktion. Wie @ KevinBurton erwähnte. Und dann add-migration "new migration",update-database
Alexander Frolov
2
Update-Database –migration: "<die zuvor angewendete Migration>" @David Sopko
Fuat
Danke @AlexanderFrolov Ich habe die Lösung aktualisiert, um Ihre Kommentare widerzuspiegeln.
David Sopko
1
Nach Schritt 2
Rahul
55

Für diejenigen, die EF Core mit ASP.NET Core v1.0.0 verwenden, hatte ich ein ähnliches Problem und verwendete die folgenden Befehle, um es zu beheben (@ DavidSopkos Beitrag wies mich in die richtige Richtung, aber die Details für EF Core unterscheiden sich geringfügig) :

Update-Database <Name of last good migration>
Remove-Migration

Zum Beispiel wurde in meiner aktuellen Entwicklung der Befehl

PM> Update-Database CreateInitialDatabase
Done.
PM> Remove-Migration
Done.
PM> 

Die Remove-Migration entfernt die zuletzt angewendete Migration. Wenn Sie ein komplexeres Szenario mit mehreren zu entfernenden Migrationen haben (ich hatte nur 2, die anfängliche und die schlechte), empfehle ich Ihnen, die Schritte in einem Dummy-Projekt zu testen.

Derzeit scheint es in EF Core (v1.0.0) keinen Befehl zum Abrufen von Migrationen zu geben. Sie müssen daher in Ihrem Migrationsordner nachsehen, was Sie getan haben. Es gibt jedoch einen netten Hilfebefehl:

PM> get-help entityframework

Beim Aktualisieren der Dastabase im VS2015 SQL Server-Objekt-Explorer wurden alle meine Daten beibehalten und die Migration, die ich zurücksetzen wollte, wurde beendet :)

Anfangs habe ich Remove-Migration selbst ausprobiert und fand den Fehlerbefehl verwirrend:

System.InvalidOperationException: Die Migration '...' wurde bereits auf die Datenbank angewendet. Wenden Sie es an und versuchen Sie es erneut. Wenn die Migration auf andere Datenbanken angewendet wurde, sollten Sie die Änderungen mithilfe einer neuen Migration zurücksetzen.

Es gibt bereits Vorschläge zur Verbesserung dieses Wortlauts, aber ich möchte, dass der Fehler etwa so lautet:

Führen Sie Update-Database (letzter guter Migrationsname) aus, um das Datenbankschema wieder in diesen Zustand zu versetzen. Dieser Befehl wendet alle Migrationen an, die nach der in Update-Database angegebenen Migration aufgetreten sind. Sie können dann Remove-Migration (zu entfernender Migrationsname) ausführen.

Die Ausgabe des EF Core-Hilfebefehls lautet wie folgt:

 PM> get-help entityframework
                     _/\__
               ---==/    \\
         ___  ___   |.    \|\
        | __|| __|  |  )   \\\
        | _| | _|   \_/ |  //|\\
        |___||_|       /   \\\/\\

TOPIC
    about_EntityFrameworkCore

SHORT DESCRIPTION
    Provides information about Entity Framework Core commands.

LONG DESCRIPTION
    This topic describes the Entity Framework Core commands. See https://docs.efproject.net for information on Entity Framework Core.

    The following Entity Framework cmdlets are included.

        Cmdlet                      Description
        --------------------------  ---------------------------------------------------
        Add-Migration               Adds a new migration.

        Remove-Migration            Removes the last migration.

        Scaffold-DbContext          Scaffolds a DbContext and entity type classes for a specified database.

        Script-Migration            Generates a SQL script from migrations.

        Update-Database             Updates the database to a specified migration.

        Use-DbContext               Sets the default DbContext to use.

SEE ALSO
    Add-Migration
    Remove-Migration
    Scaffold-DbContext
    Script-Migration
    Update-Database
    Use-DbContext
Richard Logwood
quelle
6

Sie können auch verwenden

Remove-Migration -Force

Dadurch wird die zuletzt angewendete Migration zurückgesetzt und entfernt

Daniël Tulp
quelle
4

Aktualisieren Sie zunächst Ihre letzte perfekte Migration über diesen Befehl:

Update-Database TargetMigration

Beispiel:

Update-Database -20180906131107_xxxx_xxxx

Löschen Sie dann Ihre nicht verwendete Migration manuell.

Abdus Salam Azad
quelle
2
es sollte sein: Update-Database -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides
Update-Database 20180906131107_xxxx_xxxx(kein Bindestrich) hat bei mir funktioniert. Keine Version von TargetMigrationals Schalter funktionierte. Diese Befehle scheinen ein sich bewegendes Ziel zu sein (dh sie in jeder Version zu ändern)?
Summe keine
3

Ab .NET Core 2.2 TargetMigrationscheint weg zu sein:

get-help Update-Database

NAME
    Update-Database

SYNOPSIS
    Updates the database to a specified migration.


SYNTAX
    Update-Database [[-Migration] <String>] [-Context <String>] [-Project <String>] [-StartupProject <String>] [<CommonParameters>]


DESCRIPTION
    Updates the database to a specified migration.


RELATED LINKS
    Script-Migration
    about_EntityFrameworkCore 

REMARKS
    To see the examples, type: "get-help Update-Database -examples".
    For more information, type: "get-help Update-Database -detailed".
    For technical information, type: "get-help Update-Database -full".
    For online help, type: "get-help Update-Database -online"

Das funktioniert jetzt für mich:

Update-Database -Migration 20180906131107_xxxx_xxxx

Sowie (nein -Migration Schalter):

Update-Database 20180906131107_xxxx_xxxx

Außerdem können Sie Migrationsordner nicht mehr sauber löschen, ohne dass Ihr Modell-Snapshot nicht mehr synchron ist. Wenn Sie dies auf die harte Tour lernen und mit einer leeren Migration enden, bei der Sie wissen, dass Änderungen vorgenommen werden sollten, können Sie diese ausführen (für die letzte Migration sind keine Schalter erforderlich):

Remove-migration

Es wird das Chaos beseitigen und Sie dorthin zurückversetzen, wo Sie sein müssen, obwohl der letzte Migrationsordner manuell gelöscht wurde.

Summe keine
quelle
0

Für EF 6 ist hier ein Einzeiler, wenn Sie viel in der Entwicklung umbauen. Aktualisieren Sie einfach die Vars und verwenden Sie dann weiterhin den Aufwärtspfeil in der Paketmanager-Konsole, um zu spülen und zu wiederholen.

$lastGoodTarget = "OldTargetName"; $newTarget = "NewTargetName"; Update-Database -TargetMigration "$lastGoodTarget" -Verbose; Add-Migration "$newTarget" -Verbose -Force

Warum ist das notwendig, fragst du? Sie sind sich nicht sicher, für welche EF6-Versionen dies gilt, aber wenn Ihr neues Migrationsziel bereits angewendet wurde, wird die Verwendung von '-Force' zum erneuten Gerüstbau in Add-Migration das eigentliche Gerüst nicht neu erstellen, sondern eine neue Datei erstellen (dies ist gut was aber, weil du dein 'Down' nicht verlieren willst). Das obige Snippet führt bei Bedarf zuerst das 'Down' durch, dann funktioniert -Force ordnungsgemäß, um das Gerüst wieder aufzubauen.

Frau
quelle