Rollback di Entity Framework e rimozione della migrazione errata


174

Sto usando EF 6.0 per il mio progetto in C # con migrazioni e aggiornamenti manuali. Ho circa 5 migrazioni nel database, ma mi sono reso conto che l'ultima migrazione è stata negativa e non la voglio. So che posso eseguire il rollback a una migrazione precedente, ma quando aggiungo una nuova migrazione (fissa) ed eseguo Update-Database, viene applicata anche la migrazione errata.

Stavo cercando di ripristinare la migrazione precedente ed eliminare il file con una migrazione errata. Ma poi, quando provo ad aggiungere una nuova migrazione, ottengo un errore durante l'aggiornamento del database, perché il file di migrazione è danneggiato (in particolare, la prima riga di codice rinomina la tabella da A a B e le righe successive, EF sta cercando di aggiornare la tabella con nome A - forse è un bug di EF).

C'è qualche query che posso eseguire, che direbbe a EF qualcosa come "Dimentica l'ultima migrazione come se non fosse mai esistita, era male"? Qualcosa come Rimuovere-Migrazione.

Modifica1 Ho trovato la soluzione adatta a me. Modifica del modello in buono stato ed esecuzione Add-Migration TheBadMigration -Force. Ciò ripercorrerà l'ultima migrazione non applicata.

Comunque, questo non risponde ancora completamente alla domanda originale. Se aggiorno Database alla migrazione errata, non ho trovato il modo corretto di eseguire il rollback e creare una nuova migrazione, escludendo quella errata.

Grazie


Ho dovuto riavviare Visual Studio e poi ha iniziato a funzionare correttamente. Questo mi è già successo un paio di volte, sempre dopo aver fatto confusione con le migrazioni senza aggiornare effettivamente il database, quindi c'è qualcosa di strano che sta succedendo con gli strumenti lì.
Andrei Dvoynos,

Risposte:


167

Hai 2 opzioni:

  • Puoi prendere il Down dalla migrazione errata e inserirlo in una nuova migrazione (dovrai anche apportare le modifiche successive al modello). Questo sta effettivamente passando a una versione migliore.

    Uso questa opzione su cose che sono andate in più ambienti.

  • L'altra opzione è quella di eseguire effettivamente Update-Database –TargetMigration: TheLastGoodMigrationil database distribuito e quindi eliminare la migrazione dalla soluzione. Questo è un po 'l'alternativa di Hulk Smash e richiede che venga eseguito su qualsiasi database distribuito con la versione non valida.

    Nota: per ripetere la migrazione è possibile utilizzare Add-Migration [existingname] -Force. Questo tuttavia sovrascriverà la tua migrazione esistente, quindi assicurati di farlo solo se hai rimosso la migrazione esistente dal database. Ciò equivale a eliminare ed eseguire il file di migrazione esistenteadd-migration

    Uso questa opzione durante lo sviluppo.


1
L'opzione Hulk Smash non funziona. Non ho ancora applicato la migrazione errata al database. Ho provato, ma non funzionava, perché i nomi delle tabelle che ho specificato nella domanda originale. La prima opzione non mi piace molto, perché sembra che dovrei cambiare il codice della migrazione. Se lo faccio male, posso rompere tutto.
Martin Brabec,

8
Se non hai ancora applicato la migrazione errata, non c'è nulla che ti impedisca di eliminarla e di riprogrammare o correggere la migrazione interrotta.
Non mi è piaciuto il

4
"Hulk Smash" è la risposta, funziona per me durante lo sviluppo e voglio aggiungere qualcosa alla migrazione che mi mancava. Penso che i motivi per cui non ha funzionato per Martin non siano correlati (o probabilmente legati alla modifica manuale dello schema del database)
rethenhouser2

1
@BenRethmeier come regola generale Uso l'opzione Hulk Smash solo mentre sto sviluppando. In prod creo sempre una nuova migrazione per correggere il problema. Il motivo è che è necessario un intervento manuale se si esegue il downgrade del database. Non mi piace niente che necessiti di intervento manuale in prod.
Non amato il

1
HULK SMASH !!!! --- Ho provato a essere gentile ma EF non stava giocando - sono tornato all'ultimo conosciuto - (Backup dei file di migrazione) Eliminato, Aggiunto Migrazione - Forza - Rinominato in precedente e copiato il codice. Aggiorna database quindi aggiunto la seconda migrazione allo stesso modo - nessun errore - ritorno alla normalità
Traci

127

Come indica la domanda, ciò si applica a una migrazione in un ambiente di tipo di sviluppo che non è stato ancora rilasciato.

Questo problema può essere risolto in questi passaggi: ripristinare il database sull'ultima migrazione valida, eliminare la migrazione errata dal progetto Entity Framework, generare una nuova migrazione e applicarla al database. Nota: a giudicare dai commenti, questi esatti comandi potrebbero non essere più applicabili se si utilizza EF Core.

Passaggio 1: ripristinare una migrazione precedente

Se non hai ancora applicato la tua migrazione, puoi saltare questa parte. Per ripristinare lo schema del database su un punto precedente emettere il comando Aggiorna database con l'opzione -TargetMigration specificare l'ultima migrazione valida. Se il codice del framework dell'entità risiede in un progetto diverso nella soluzione, potrebbe essere necessario utilizzare l'opzione '-Project' o cambiare il progetto predefinito nella console del gestore pacchetti.

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

Per ottenere il nome dell'ultima migrazione valida, utilizzare il comando 'Get-Migrations' per recuperare un elenco dei nomi delle migrazioni che sono stati applicati al database.

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

Questo elenco mostra prima le migrazioni applicate più recenti. Scegli la migrazione che si verifica nell'elenco dopo quella a cui desideri eseguire il downgrade, ovvero quella applicata prima di quella a cui desideri eseguire il downgrade. Ora emetti un Database di aggiornamento.

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

Tutte le migrazioni applicate dopo quella specificata verranno ridimensionate in ordine, a partire dall'ultima migrazione applicata per prima.

Passaggio 2: elimina la migrazione dal progetto

remove-migration name_of_bad_migration

Se il remove-migrationcomando non è disponibile nella versione di Entity Framework, eliminare manualmente i file della migrazione indesiderata nella cartella "Migrazioni" del progetto EF. A questo punto, sei libero di creare una nuova migrazione e applicarla al database.

Passaggio 3: aggiungi la nuova migrazione

add-migration my_new_migration

Passaggio 4: applicare la migrazione al database

update-database

6
Con EF Core sembra che Get-Migrations sia stato rimosso.
Kevin Burton,

1
Passo 2 ! - Funzionalità molto utile. Come menzionato @KevinBurton. E poi add-migration "new migration",update-database
Alexander Frolov, il

2
Update-Database –migration: "<la migrazione applicata prima di essa>" @David Sopko
Fuat

Grazie @AlexanderFrolov ho aggiornato la soluzione per riflettere i tuoi commenti.
David Sopko,

1
dobbiamo usare remove-migration dopo il passaggio 2
Rahul

55

Per quelli che usano EF Core con ASP.NET Core v1.0.0 ho avuto un problema simile e ho usato i seguenti comandi per correggerlo (il post di @ DavidSopko mi ha indicato nella giusta direzione, ma i dettagli sono leggermente diversi per EF Core) :

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

Ad esempio, nel mio sviluppo attuale il comando è diventato

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

Remove-Migration rimuoverà l'ultima migrazione che hai applicato. Se hai uno scenario più complesso con più migrazioni da rimuovere (ne avevo solo 2, quella iniziale e quella negativa), ti suggerisco di testare i passaggi in un progetto fittizio.

Al momento non sembra esserci un comando Get-Migrations in EF Core (v1.0.0), quindi devi cercare nella cartella delle migrazioni e conoscere ciò che hai fatto. Tuttavia, c'è un bel comando di aiuto:

PM> get-help entityframework

Con l'aggiornamento di dastabase in VS2015 SQL Server Object Explorer, tutti i miei dati sono stati conservati e la migrazione che volevo ripristinare era sparita :)

Inizialmente ho provato Remove-Migration da solo e ho trovato confuso il comando di errore:

System.InvalidOperationException: la migrazione '...' è già stata applicata al database. Annulla l'applicazione e riprova. Se la migrazione è stata applicata ad altri database, prendere in considerazione la possibilità di ripristinare le modifiche utilizzando una nuova migrazione.

Esistono già suggerimenti per migliorare questa formulazione, ma vorrei che l'errore dicesse qualcosa del genere:

Eseguire Update-Database (ultimo nome di migrazione valido) per riportare lo schema del database a quello stato. Questo comando applicherà tutte le migrazioni avvenute dopo la migrazione specificata in Update-Database. È quindi possibile eseguire Remove-Migration (nome della migrazione da rimuovere)

L'output del comando di aiuto EF Core è il seguente:

 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

6

Puoi anche usare

Remove-Migration -Force

Ciò ripristinerà e rimuoverà l'ultima migrazione applicata


4

Innanzitutto, aggiorna l'ultima migrazione perfetta tramite questo comando:

Update-Database TargetMigration

Esempio:

Update-Database -20180906131107_xxxx_xxxx

E quindi eliminare manualmente la migrazione inutilizzata.


2
dovrebbe essere: Update-Database -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides

Update-Database 20180906131107_xxxx_xxxx(nessun trattino) ha funzionato per me. Nessuna versione di TargetMigrationcome switch ha funzionato. Questi comandi sembrano essere un bersaglio mobile (cioè cambiarli in ogni versione)?
Somma nessuno

3

A partire da .NET Core 2.2, TargetMigrationsembra essere sparito:

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"

Quindi questo funziona per me ora:

Update-Database -Migration 20180906131107_xxxx_xxxx

Così come (nessun -Migrationinterruttore):

Update-Database 20180906131107_xxxx_xxxx

In una nota aggiunta, non è più possibile eliminare in modo pulito le cartelle di migrazione senza sincronizzare l'istantanea del modello. Quindi, se lo impari nel modo più duro e finisci con una migrazione vuota in cui sai che dovrebbero esserci delle modifiche, puoi eseguire (non sono necessari switch per l'ultima migrazione):

Remove-migration

Pulirà il disordine e ti riporterà dove devi essere, anche se l'ultima cartella di migrazione è stata eliminata manualmente.


0

Per EF 6 ecco un one-liner se stai ri-impalcando molto in fase di sviluppo. Basta aggiornare le variabili e quindi continuare a utilizzare la freccia su nella console di Gestione pacchetti per risciacquare e ripetere.

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

Perché è necessario chiedere? Non sono sicuro di quali versioni di EF6 si applichino, ma se il tuo nuovo obiettivo di migrazione è già stato applicato, utilizzare '-Force' per ricostruire il ponteggio in Add-Migration non eseguirà nuovamente il ponteggio, ma creerà invece un nuovo file (questo è un buon cosa però perché non vorresti perdere il tuo 'Down'). Lo snippet precedente esegue prima "Giù", se necessario, quindi -Force funziona correttamente per il reimpalcatura.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.