web-dev-qa-db-fra.com

Retour en arrière sur Entity Framework et suppression de la migration incorrecte

J'utilise EF 6.0 pour mon projet en C # avec des migrations et des mises à jour manuelles. J'ai environ 5 migrations sur la base de données, mais j'ai réalisé que la dernière migration était mauvaise et que je ne le voulais pas. Je sais que je peux revenir à une migration précédente, mais lorsque j'ajoute une nouvelle migration (fixe) et exécute Update-Database, même la migration incorrecte est appliquée.

J'essayais de revenir à la migration précédente et de supprimer le fichier avec une migration incorrecte. Mais ensuite, lorsque j'essaie d'ajouter une nouvelle migration, une erreur survient lors de la mise à jour de la base de données, car le fichier de migration est corrompu (plus précisément, la première ligne de code renomme la table A en B et les lignes suivantes, EF tente de la mettre à jour avec nom A - c’est peut-être un bogue EF).

Existe-t-il une requête que je peux exécuter, qui dirait à EF quelque chose comme: "Oubliez la dernière migration comme si elle n'avait jamais existé, c'était mauvais"? Quelque chose comme Remove-Migration.

Edit1 J'ai trouvé la solution qui me convenait. Changer le modèle dans le bon état et lancer Add-Migration TheBadMigration -Force. Cela ré-échafaudera la dernière migration, non appliquée.

Quoi qu'il en soit, cela ne répond toujours pas complètement à la question initiale. Si je mets à jour UpdateDatabase à la mauvaise migration, je n’ai pas trouvé le bon moyen de revenir en arrière et de créer une nouvelle migration, en excluant la mauvaise. 

Merci

127
Martin Brabec

Vous avez 2 options: 

  • Vous pouvez retirer le Down de la mauvaise migration et le placer dans une nouvelle migration (vous devrez également apporter les modifications suivantes au modèle). Cela revient effectivement à une meilleure version. 

    J'utilise cette option sur des choses qui sont passées dans plusieurs environnements.

  • L'autre option consiste à exécuter Update-Database –TargetMigration: TheLastGoodMigration sur votre base de données déployée, puis à supprimer la migration de votre solution. C’est un peu l’alternative de smash de Hulk qui nécessite que cela soit fait contre toute base de données déployée avec la version incorrecte.

    Remarque: pour réaffecter la migration, vous pouvez utiliser Add-Migration [existingname] -Force. Cependant, cela va écraser votre migration existante, alors assurez-vous de ne le faire que si vous avez supprimé la migration existante de la base de données. Cela équivaut à supprimer le fichier de migration existant et à exécuter add-migration.

    J'utilise cette option lors du développement.

137
Luke McGregor

Comme l'indique la question, cela s'applique à une migration dans un environnement de type de développement qui n'a pas encore été publiée.

Ce problème peut être résolu en ces étapes. La première étape consiste à restaurer votre base de données vers la dernière migration correcte, puis à supprimer la migration incorrecte de votre projet Entity Framework. À ce stade, vous pourrez générer une nouvelle migration et appliquer à la base de données. Remarque: à en juger par les commentaires, ces commandes exactes risquent de ne plus être applicables si vous utilisez EF Core.

Étape 1: Restaurer une migration précédente

Pour restaurer votre schéma de base de données à un point précédent, utilisez: 

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

Spécifier la dernière bonne migration. Si vous n'avez pas encore appliqué votre migration, vous pouvez ignorer cette partie.

Utilisez la commande Get-Migrations pour obtenir une liste des noms de migration appliqués à votre base de données. 

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

Cette liste affiche d'abord les dernières migrations appliquées. Choisissez la migration qui apparaît dans la liste après celle que vous souhaitez rétrograder, c'est-à-dire celle appliquée avant celle que vous souhaitez rétrograder.

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

Toutes les migrations appliquées après celle spécifiée seront rétrogradées dans l'ordre, en commençant par la dernière migration appliquée en premier.

Étape 2: Supprimez votre migration du projet

Vous pouvez maintenant supprimer la migration incorrecte du dossier "Migrations" de votre projet EF. À ce stade, vous êtes libre de créer une nouvelle migration et de l'appliquer à la base de données.

Étape 3: Ajoutez votre nouvelle migration

add-migration "new migration"

Étape 4: appliquez votre migration à la base de données

update-database
81
David Sopko

Pour ceux qui utilisaient EF Core avec ASP.NET Core v1.0.0 j’avais un problème similaire et utilisais les commandes suivantes pour le corriger (Le message de @ DavidSopko m’a orienté dans la bonne direction, mais les détails diffèrent légèrement EF Core):

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

Par exemple, dans mon développement actuel, la commande est devenue

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

Remove-Migration supprimera la dernière migration que vous avez appliquée. Si vous devez supprimer un scénario plus complexe comportant plusieurs migrations (je n'en avais que 2, l'initiale et la mauvaise), je vous suggère de tester les étapes d'un projet factice.

Il ne semble pas qu'il y ait actuellement de commande Get-Migrations dans EF Core (v1.0.0). Vous devez donc consulter votre dossier de migration et vous familiariser avec ce que vous avez fait. Cependant, il existe une commande d'aide Nice:

PM> get-help entityframework

Actualisation de la base de données dans l'Explorateur d'objets SQL Server VS2015: toutes mes données ont été préservées et la migration que je voulais annuler avait disparu :)

Au départ, j’ai essayé moi-même avec Remove-Migration et j’ai trouvé la commande d’erreur confuse:

System.InvalidOperationException: la migration '...' a déjà été appliqué à la base de données. Désappliquez-le et réessayez. Si la migration a été appliqué à d'autres bases de données, envisagez de revenir à ses modifications en utilisant une nouvelle migration.

Il y a déjà des suggestions pour améliorer cette formulation, mais j'aimerais l'erreur de dire quelque chose comme ceci:

Exécutez Update-Database (dernier nom de migration correct) pour rétablir le schéma de base de données sur cet état. Cette commande sera désappliquer toutes les migrations effectuées après la migration spécifiée à Base de données de mise à jour. Vous pouvez ensuite exécuter Remove-Migration (nom de la migration à supprimer)

La sortie de la commande d’aide EF Core suit:

 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

Commencez par mettre à jour votre dernière migration parfaite via cette commande: 

Update-Database –TargetMigration

Exemple:

Update-Database -20180906131107_xxxx_xxxx

Et puis supprimez votre migration inutilisée manuellement.

3
Abdus Salam Azad

À partir de .NET Core 2.2, TargetMigration semble avoir disparu:

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"

Donc cela fonctionne pour moi maintenant:

Update-Database -Migration 20180906131107_xxxx_xxxx

De même que (pas de commutateur -Migration):

Update-Database 20180906131107_xxxx_xxxx

Sur une note ajoutée, vous ne pouvez plus supprimer proprement des dossiers de migration sans désynchroniser votre instantané de modèle. Donc, si vous apprenez cela à la dure et que vous vous retrouvez avec une migration vide où vous savez qu'il devrait y avoir des changements, vous pouvez exécuter (aucun commutateur n'est nécessaire pour la dernière migration):

Remove-migration

Il nettoiera le désordre et vous ramènera là où vous devez être, même si le dernier dossier de migration a été supprimé manuellement.

2
Sum None

Pour EF 6, voici un one-liner si vous ré-échafaudez beaucoup de développement. Il suffit de mettre à jour les vars, puis de continuer à utiliser la flèche vers le haut de la console du gestionnaire de paquets pour le rincer et le répéter.

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

Pourquoi est-ce nécessaire que vous demandez? Vous ne savez pas exactement quelles versions d'EF6 sont concernées, mais si votre nouvelle cible de migration a déjà été appliquée, alors, utilisez '-Force' pour rééchafauder dans Add-Migration, mais ne créerez pas un nouveau fichier parce que vous ne voudriez pas perdre votre 'Down'). L'extrait ci-dessus fait le 'Down' d'abord si nécessaire, puis -Force fonctionne correctement pour ré-échafauder.

0
madamission

Vous pouvez aussi utiliser

Remove-Migration -Force

Cela annulera et supprimera la dernière migration appliquée

0
Daniël Tulp