Comment obtenir EF en synchronisation avec le code sans perdre de données lorsque Update-database renvoie le message suivant
Message d'erreur: System.Data.SqlClient.SqlException (0x80131904): Il existe déjà un objet nommé '' dans la base de données.
Au départ, j’écrivais cette question comme une question à réponse automatique, car j’avais eu du mal à résoudre le problème pendant un certain temps, de même que quelques collègues, mais malheureusement, ma réponse a été supprimée et je ne peux pas la récupérer.
Étant donné que c'est une situation qui, je suppose, peut se produire plusieurs fois alors que les gens tentent de "nettoyer" les anciennes migrations, je pensais que je la documenterais avec des instructions pas à pas.
Description de la situation dans laquelle nous nous sommes retrouvés : Impossible de créer une nouvelle base de données locale car le script init était incomplet et d’appliquer des mises à jour à la base de production car les scripts de migration créent des tables déjà existantes. Et nous ne voulions pas supprimer les données de production.
Symptôme : Impossible d'exécuter Update-Database car il tente d'exécuter le script de création et la base de données contient déjà des tables portant le même nom.
Message d'erreur: System.Data.SqlClient.SqlException (0x80131904): Il existe déjà un objet nommé '' dans la base de données.
Problème : pour mieux comprendre cela, je vous conseillerais de regarder les deux vidéos référencées ici: https://msdn.microsoft.com/en-us/library/dn481501(v=vs.113).aspx
Pour résumer, EF comprend où se trouve la base de données actuelle par rapport à celle où se trouve le code, en se basant sur une table de la base de données appelée dbo .__ MigrationHistory. Lorsqu'il examine les scripts de migration, il tente de reconsiler où il en était avec les scripts. Si ce n'est pas le cas, il essaie simplement de les appliquer dans l'ordre. Cela signifie que cela revient au script de création initial et que si vous regardez la première partie de la commande UP, il s'agira de la table CreeateTable pour la table sur laquelle l'erreur se produisait.
Solution : Nous devons persuader EF de penser que la base de données actuelle est à jour, sans "appliquer" ces commandes CreateTable, car la base de données de production existe déjà. Une fois la base de données de production définie, nous devons également pouvoir créer des bases de données locales.
Étape 1: Nettoyage de la base de données de production Commencez par effectuer une sauvegarde de votre base de données de production. Dans SSMS, cliquez avec le bouton droit de la souris sur la base de données, sélectionnez "Tâches> Exporter l'application de niveau données ..." et suivez les instructions. Ouvrez votre base de données de production et supprimez / supprimez la table dbo .__ MigrationHistory.
Étape 2: nettoyage de l'environnement local Ouvrez votre dossier de migration et supprimez-le. Je suppose que vous pouvez récupérer tout ça de git si nécessaire.
Étape 3: Recréer l'initiale Dans le gestionnaire de packages, exécutez "Enable-Migrations" (EF vous invitera à utiliser -ContextTypeName si vous avez plusieurs contextes). Exécutez "Add-Migration Initial -verbose". Cela créera le script initial pour créer la base de données à partir de zéro en fonction du code actuel. Si vous aviez des opérations de base dans le fichier Configuration.c précédent, copiez-le ensuite.
Étape 4: Trick EF À ce stade, si nous utilisions Update-Database , nous obtiendrions l'erreur d'origine. Donc, nous devons faire croire à EF qu’elle est à jour, sans exécuter ces commandes. Alors, allez dans la méthode Up dans la migration initiale que vous venez de créer et commentez le tout.
Étape 5: Mise à jour de la base de données En l'absence de code à exécuter sur le processus Up, EF créera la table dbo .__ MigrationHistory avec l'entrée correcte pour indiquer qu'il a exécuté ce script correctement. Allez vérifier si vous aimez. Maintenant, décommentez ce code et enregistrez. Vous pouvez exécuter Update-Database à nouveau si vous voulez vérifier que EF pense être à jour. Il ne lancera pas l'étape Up avec toutes les commandes CreateTable car il pense que c'est déjà fait.
Etape 6: Confirmez que EF est ACTUELLEMENT à jour Si vous aviez un code pour lequel aucune migration n’avait été appliquée, c’est ce que j’ai fait ...
Exécuter "Add-Migration MissingMigrations" Ceci créera pratiquement un script vide. Comme le code existait déjà, il y avait en fait les bonnes commandes pour créer ces tables dans le script de migration initial. Je viens donc de couper les commandes CreateTable et les commandes de largage équivalentes dans les méthodes Up et Down.
Maintenant, exécutez à nouveau Update-Database et observez-le exécuter votre nouveau script de migration, en créant les tables appropriées dans la base de données.
Étape 7: Confirmer à nouveau et commettre. Construire, tester, exécuter. Assurez-vous que tout fonctionne, puis validez les modifications.
Étape 8: Indiquez au reste de votre équipe comment procéder. Lors de la mise à jour de la personne suivante, EF ne saura pas ce qui l’a frappé étant donné que les scripts exécutés auparavant n’existent pas. Mais, en supposant que les bases de données locales puissent être supprimées et recréées, tout cela est bien. Ils devront supprimer leur base de données locale et l'ajouter à nouveau à partir d'EF. S'ils avaient des modifications locales et des migrations en attente, je recommanderais qu'ils créent à nouveau leur base de données sur maître, basculent vers leur branche de fonctionnalité et recréent ces scripts de migration à partir de zéro.