it-swarm.com.de

Entity Framework-Rollback und Entfernen einer fehlerhaften Migration

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 mir wurde klar, dass die letzte Migration schlecht war und ich sie nicht möchte. Ich weiß, dass ich ein Rollback zu einer vorherigen Migration ausführen kann. Wenn ich jedoch eine neue (feste) Migration hinzufüge und Update-Database ausführte, wird sogar die fehlerhafte Migration angewendet.

Ich habe versucht, die vorherige Migration rückgängig zu machen und die Datei mit einer fehlerhaften Migration zu löschen. Wenn ich jedoch versuche, eine neue Migration hinzuzufügen, erhalte ich einen Fehler beim Aktualisieren der Datenbank, da die Migrationsdatei beschädigt ist (insbesondere benennt die erste Zeile des Codes die Tabelle A in B um und die nächsten Zeilen sind, EF versucht, die Tabelle zu aktualisieren.) Name A - vielleicht handelt es sich um einen EF-Fehler).

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

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

Auf jeden Fall ist die ursprüngliche Frage immer noch nicht vollständig beantwortet. Wenn ich UpdateDatabase für die fehlerhafte Migration durchführe, habe ich keinen guten Weg gefunden, wie ich ein Rollback durchführen und eine neue Migration erstellen kann, mit Ausnahme der schlechten. 

Vielen Dank

127
Martin Brabec

Sie haben 2 Möglichkeiten: 

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

    Ich verwende diese Option für Dinge, die in mehreren Umgebungen stattgefunden haben.

  • Die andere Option besteht darin, Update-Database –TargetMigration: TheLastGoodMigration für Ihre bereitgestellte Datenbank auszuführen und die Migration anschließend aus Ihrer Lösung zu löschen. Dies ist gewissermaßen die hulk-smash-Alternative und erfordert, dass dies für jede Datenbank durchgeführt wird, die mit der fehlerhaften Version implementiert wurde.

    Hinweis: Um die Migration neu zu verteilen, können Sie Add-Migration [existingname] -Force verwenden. Dadurch wird jedoch Ihre vorhandene Migration überschrieben. Stellen Sie daher sicher, dass Sie dies nur tun, wenn Sie die vorhandene Migration aus der Datenbank entfernt haben. Dies geschieht genauso wie das Löschen der vorhandenen Migrationsdatei und das Ausführen von add-migration.

    Ich benutze diese Option während der Entwicklung.

137
Luke McGregor

Wie die Frage zeigt, gilt dies für eine Migration in einer Entwicklungsumgebung, die noch nicht freigegeben wurde.

Dieses Problem kann in diesen Schritten behoben werden. Zunächst müssen Sie Ihre Datenbank auf die letzte einwandfreie Migration zurücksetzen und anschließend die fehlerhafte Migration aus Ihrem Entity Framework-Projekt löschen. An diesem Punkt können Sie eine neue Migration generieren und anwenden es in die Datenbank. Hinweis: Nach den Kommentaren zu urteilen, sind diese exakten Befehle möglicherweise nicht mehr anwendbar, wenn Sie EF Core verwenden.

Schritt 1: Wiederherstellung einer vorherigen Migration

Um Ihr Datenbankschema auf einen früheren Punkt zurückzusetzen, verwenden Sie die folgenden Befehle: 

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

Festlegen der letzten guten Migration. Wenn Sie die Migration noch nicht angewendet haben, können Sie diesen Teil überspringen.

Mit dem Befehl "Get-Migrations" können Sie eine Liste der Migrationsnamen abrufen, 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 stattfindet, zu der Sie ein Downgrade durchführen möchten, dh der Migration, die vor der Migration vorgenommen wurde, die Sie Downgrade durchführen möchten.

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

Alle Migrationen, die nach der angegebenen Migration ausgeführt werden, werden in der Reihenfolge heruntergestuft, beginnend mit der zuletzt durchgeführten Migration.

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

Sie können jetzt die fehlerhafte Migration aus dem Ordner "Migrations" Ihres EF-Projekts löschen. An diesem Punkt können Sie eine neue Migration erstellen und auf die Datenbank anwenden.

Schritt 3: Neue Migration hinzufügen

add-migration "new migration"

Schritt 4: Übernehmen Sie die Migration auf die Datenbank

update-database
81
David Sopko

Bei der Verwendung von EF Core mit ASP.NET Core v1.0.0 hatte ich ein ähnliches Problem und verwendete die folgenden Befehle, um das Problem zu beheben (@DeventsSopkos Beitrag wies mich in die richtige Richtung, aber die Details unterscheiden sich geringfügig EF Core):

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 letzte von Ihnen angewendete Migration. Wenn Sie ein komplexeres Szenario mit mehreren zu entfernenden Migrationen haben (ich hatte nur zwei, die erste und die schlechte), empfehle ich Ihnen, die Schritte in einem Dummy-Projekt zu testen.

Derzeit gibt es in EF Core (Version 1.0.0) offenbar keinen Befehl "Get-Migrations". Daher müssen Sie in Ihrem Migrationsordner nachsehen und sich mit dem, was Sie getan haben, vertraut machen. Es gibt jedoch einen Nice-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 wiederherstellen wollte, war verschwunden :)

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

System.InvalidOperationException: Die Migration '...' war bereits auf die Datenbank angewendet. Unapply und versuchen Sie es erneut. Wenn die Migration auf andere Datenbanken angewendet wurde, sollten Sie die Änderungen rückgängig machen mit einer neuen Migration.

Es gibt bereits Vorschläge zur Verbesserung dieser Formulierung, aber ich möchte, dass der Fehler etwa Folgendes sagt:

Führen Sie Update-Database (letzter guter Migrationsname) aus, um das Datenbankschema wieder in diesen Zustand zu versetzen. Dieser Befehl wird Nicht zutreffend alle Migrationen, die nach der auf .__ angegebenen Migration durchgeführt wurden. Datenbank auf den neusten Stand bringen. Sie können dann Remove-Migration ausführen (zu entfernender Migrationsname).

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
42
Richard Logwood

Aktualisieren Sie zunächst Ihre letzte perfekte Migration mit diesem Befehl: 

Update-Database –TargetMigration

Beispiel:

Update-Database -20180906131107_xxxx_xxxx

Und dann löschen Sie Ihre ungenutzte Migration manuell.

3

Ab .NET Core 2.2 scheint TargetMigration 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 (kein -Migration Schalter):

Update-Database 20180906131107_xxxx_xxxx

Außerdem können Sie Migrationsordner nicht mehr sauber löschen, ohne den Model Snapshot nicht mehr synchron zu halten. Wenn Sie dies also auf die harte Tour lernen und eine leere Migration abschließen, bei der Sie wissen, dass Änderungen erforderlich sind, können Sie sie ausführen (für die letzte Migration sind keine Switches erforderlich):

Remove-migration

Es räumt das Chaos auf und bringt Sie zurück, wo Sie sein müssen, obwohl der letzte Migrationsordner manuell gelöscht wurde.

2
Sum None

Für EF 6 ist hier ein One-Liner, wenn Sie viel in der Entwicklung nachrüsten. Aktualisieren Sie einfach die Variablen und verwenden Sie dann weiterhin den Aufwärtspfeil in der Paket-Manager-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? Sie sind sich nicht sicher, welche Versionen von EF6 dies gilt. Wenn Ihr neues Migrationsziel jedoch bereits angewendet wurde, wird die Verwendung von '-Force' zum erneuten Scaffold in Add-Migration nicht tatsächlich neu erstellt, sondern eine neue Datei erstellt (dies ist gut Sache, weil Sie nicht Ihre 'Down' verlieren wollen). Das obige Snippet führt zuerst das Down aus, falls nötig, dann funktioniert -Force ordnungsgemäß, um das Gerüst neu aufzubauen.

0
madamission

Sie können auch verwenden

Remove-Migration -Force

Dadurch wird die letzte angewendete Migration zurückgesetzt und entfernt

0
Daniël Tulp