Migrations Code First avec une base de données existante
Remarque
À partir de EF4.3 uniquement : les fonctionnalités, les API, etc. présentées dans cette page ont été introduites dans Entity Framework 4.1. Si vous utilisez une version antérieure, certaines ou toutes les informations ne s’appliquent pas.
Cet article traite de l’utilisation de Migrations Code First avec une base de données existante, qui n’a pas été créée par Entity Framework.
Remarque
Cet article part du principe que vous savez comment utiliser les Migrations Code First dans des scénarios de base. Si ce n’est pas le cas, vous devez lire Migrations Code First avant de continuer.
Étape 1 : créer un modèle
Votre première étape consiste à créer un modèle Code First qui cible votre base de données existante. La rubrique Code First vers une base de données existante fournit des instructions détaillées sur la façon de procéder.
Remarque
Il est important de suivre le reste des étapes décrites dans cette rubrique avant d’apporter des modifications à votre modèle qui nécessiteraient de modifier le schéma de la base de données. Les étapes suivantes nécessitent que le modèle soit synchronisé avec le schéma de base de données.
Étape 2 : activer les migrations
L’étape suivante consiste à activer les migrations. Pour ce faire, exécutez la commande Enable-Migrationsdans la console du Gestionnaire de package.
Cette commande crée un dossier dans votre solution appelée Migrations et place une classe unique dans celle-ci appelée Configuration. La classe Configuration est l’endroit où vous configurez des migrations pour votre application, vous pouvez en savoir plus dans la rubrique Code First Migrations .
Étape 3 : ajouter une migration initiale
Une fois les migrations créées et appliquées à la base de données locale, vous pouvez également appliquer ces modifications à d’autres bases de données. Par exemple, votre base de données locale peut être une base de données de test et vous pouvez éventuellement appliquer les modifications à une base de données de production et/ou à d’autres bases de données de test de développeurs. Il existe deux options pour cette étape et celle que vous devez choisir varie en fonction du fait que le schéma d’une autre base de données est vide ou correspond actuellement au schéma de la base de données locale.
- Option 1 : utiliser le schéma existant comme point de départ. Vous devez utiliser cette approche lorsque d’autres bases de données auxquelles les migrations seront appliquées à l’avenir auront le même schéma que votre base de données locale. Par exemple, vous pouvez l’utiliser si votre base de données de test locale correspond actuellement à la v1 de votre base de données de production et que vous appliquez ultérieurement ces migrations pour mettre à jour votre base de données de production vers v2.
- Option 2 : utiliser une base de données vide comme point de départ. Vous devez utiliser cette approche lorsque d’autres bases de données auxquelles les migrations seront appliquées à l’avenir sont vides (ou n’existent pas encore). Par exemple, vous pouvez l’utiliser si vous avez commencé à développer votre application à l’aide d’une base de données de test, mais sans utiliser de migrations et que vous souhaiterez plus tard créer une base de données de production à partir de zéro.
Option 1 : utiliser le schéma existant comme point de départ
Migrations Code First utilise un instantané du modèle stocké dans la migration la plus récente pour détecter les modifications apportées au modèle (vous trouverez des informations détaillées sur cela dans Les environnements d’équipe Code First). Puisque nous allons supposer que les bases de données ont déjà le schéma du modèle actuel, nous générerons une migration vide (sans opération) qui a le modèle actuel en tant qu’instantané.
- Exécutez la commande Add-Migration InitialCreate –IgnoreChanges dans la console du Gestionnaire de package. Cela crée une migration vide avec le modèle actuel en tant qu’instantané.
- Exécutez la commande Update-Database dans la Console du Gestionnaire de Package. Cette opération applique la migration InitialCreate à la base de données. Étant donné que la migration réelle ne contient aucune modification, il ajoute simplement une ligne à la table __MigrationsHistory indiquant que cette migration a déjà été appliquée.
Option 2 : utiliser une base de données vide comme point de départ
Dans ce scénario, nous avons besoin de Migrations pour pouvoir créer l’intégralité de la base de données à partir de zéro, y compris les tables déjà présentes dans notre base de données locale. Nous allons générer une migration InitialCreate qui inclut la logique pour créer le schéma existant. Nous allons ensuite faire en sorte que cette migration apparaisse dans notre base de données existante comme si elle avait déjà été appliquée.
- Exécutez la commande Add-Migration InitialCreate dans la console du Gestionnaire de package. Cela crée une migration pour créer le schéma existant.
- Commentez tout le code dans la méthode Up de la migration nouvellement créée. Cela nous permettra « d'appliquer » la migration vers la base de données locale sans essayer de recréer toutes les tables et d’autres qui y existent déjà.
- Exécutez la commande Update-Database dans la Console du Gestionnaire de Package. Cette opération applique la migration InitialCreate à la base de données. Étant donné que la migration réelle ne contient aucune modification (car nous les avons temporairement commentés), il ajoute simplement une ligne à la table __MigrationsHistory indiquant que cette migration a déjà été appliquée.
- Annulez le commentaire du code dans la méthode Up. Cela signifie que lorsque cette migration est appliquée aux bases de données futures, le schéma qui existait déjà dans la base de données locale sera créé par des migrations.
Éléments à prendre en considération
Il existe quelques éléments à prendre en compte lors de l’utilisation de Migrations sur une base de données existante.
Les noms par défaut/calculés peuvent ne pas correspondre au schéma existant
Migrations spécifie explicitement des noms pour les colonnes et les tables lorsque cela génère une structure de migrations. Toutefois, il existe d’autres objets de base de données que Migrations calcule un nom par défaut lors de l’application des migrations. Cela inclut les index et les contraintes de clé étrangère. Lorsque vous ciblez un schéma existant, ces noms calculés peuvent ne pas correspondre à ce qui existe réellement dans votre base de données.
Voici quelques exemples de situations dans lesquelles vous devez en tenir compte :
Si vous avez utilisé « Option 1 : utiliser le schéma existant comme point de départ » à l’étape 3 :
- Si des modifications ultérieures dans votre modèle nécessitent la modification ou la suppression de l’un des objets de base de données nommés différemment, vous devez modifier la migration générée pour spécifier le nom correct. Les API Migrations ont un paramètre « Name » facultatif qui vous permet de le faire. Par exemple, votre schéma existant peut avoir une table Publication avec une colonne de clé étrangère BlogId qui a un index nommé IndexFk_BlogId. Toutefois, par défaut, les migrations s’attendent à ce que cet index soit nommé IX_BlogId. Si vous apportez une modification à votre modèle qui entraîne la suppression de cet index, vous devez modifier l’appel DropIndex généré automatiquement pour spécifier le nom IndexFk_BlogId.
Si vous avez utilisé « Option 2 : utiliser une base de données vide comme point de départ » à l’étape 3 :
- La tentative d’exécution de la méthode Down de la migration initiale (autrement dit, la restauration d’une base de données vide) sur votre base de données locale peut échouer, car Migrations essaie de supprimer des index et des contraintes de clé étrangère en utilisant des noms incorrects. Cela affecte uniquement votre base de données locale, car d’autres bases de données seront créées à partir de zéro avec la méthode Up de la migration initiale. Si vous souhaitez rétrograder votre base de données locale existante à un état vide, il est plus facile de le faire manuellement, soit en supprimant la base de données, soit en supprimant toutes les tables. Après cette rétrogradation initiale, tous les objets de base de données seront recréés avec les noms par défaut, de sorte que ce problème ne se présentera plus.
- Si les modifications futures de votre modèle nécessitent la modification ou la suppression de l’un des objets de base de données nommés différemment, cela ne fonctionnera pas sur votre base de données locale existante, car les noms ne correspondent pas aux valeurs par défaut. Toutefois, elle fonctionnera sur les bases de données créées « à partir de zéro », car elles auront utilisé les noms par défaut choisis par Migrations. Vous pouvez effectuer ces modifications manuellement sur votre base de données existante locale, ou envisager de demander à Migrations de recréer votre base de données à partir de zéro, comme il le fera sur d’autres ordinateurs.
- Les bases de données créées avec la méthode Up de votre migration initiale peuvent différer légèrement de la base de données locale, car les noms par défaut calculés pour les index et les contraintes de clé étrangère seront utilisés. Vous pouvez également vous retrouver avec des index supplémentaires, car les migrations créent des index sur des colonnes clés étrangères par défaut. Cela n’a peut-être pas été le cas dans votre base de données locale d’origine.
Tous les objets de base de données ne sont pas représentés dans le modèle
Les objets de base de données qui ne font pas partie de votre modèle ne seront pas gérés par Migrations. Cela peut inclure des vues, des procédures stockées, des autorisations, des tables qui ne font pas partie de votre modèle, des index supplémentaires, etc.
Voici quelques exemples de situations dans lesquelles vous devez en tenir compte :
- Quelle que soit l’option que vous avez choisie à l’étape 3, si les modifications futures de votre modèle nécessitent la modification ou la suppression de ces objets supplémentaires, Migrations ne saura pas effectuer ces modifications. Par exemple, si vous supprimez une colonne sur laquelle se trouve un index supplémentaire, Migrations ne saura pas supprimer l’index. Vous devez ajouter cela manuellement à la migration générée automatiquement.
- Si vous avez utilisé « Option 2 : utiliser une base de données vide comme point de départ », ces objets supplémentaires ne seront pas créés avec la méthode Up de votre migration initiale. Vous pouvez modifier les méthodes Up et Down pour prendre en charge ces objets supplémentaires si vous le souhaitez. Pour les objets qui ne sont pas pris en charge en mode natif dans l’API Migrations, comme les vues, vous pouvez utiliser la méthode Sql pour exécuter du code SQL brut afin de les créer/les supprimer.