Migrations Code First avec une base de données existante

Notes

EF4.3 Et versions ultérieures : les fonctionnalités, LES API, etc. abordé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, une base de données qui n’a pas été créée par Entity Framework.

Notes

Cet article part du principe que vous savez utiliser 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. Le Code First à une rubrique de base de données existante fournit des instructions détaillées sur la façon de procéder.

Notes

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 des modifications dans le schéma de 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-Migrations dans Gestionnaire de package Console.

Cette commande crée un dossier dans votre solution appelée Migrations et place une seule classe à l’intérieur de 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 Migrations Code First.

É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 également 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 selon que le schéma d’autres bases 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 ultérieurement 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 à 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 voudrez par la suite 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 à ce sujet dans Migrations Code First dans les environnements d’équipe). Étant donné que nous allons supposer que les bases de données ont déjà le schéma du modèle actuel, nous allons générer une migration vide (sans opération) qui a le modèle actuel en tant qu’instantané.

  1. Exécutez la commande Add-Migration InitialCreate –IgnoreChanges dans Gestionnaire de package Console. Cela crée une migration vide avec le modèle actuel en tant qu’instantané.
  2. Exécutez la commande Update-Database dans Gestionnaire de package Console. Cette opération applique la migration InitialCreate à la base de données. Étant donné que la migration réelle ne contient aucune modification, elle 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 notre base de données existante ressemble à cette migration a déjà été appliquée.

  1. Exécutez la commande Add-Migration InitialCreate dans Gestionnaire de package Console. Cela crée une migration pour créer le schéma existant.
  2. 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, etc. qui existent déjà.
  3. Exécutez la commande Update-Database dans Gestionnaire de package Console. 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ées), il ajoute simplement une ligne à la table __MigrationsHistory indiquant que cette migration a déjà été appliquée.
  4. Supprimez le commentaire du code dans la méthode Up. Cela signifie que lorsque cette migration est appliquée aux futures bases de données, le schéma qui existait déjà dans la base de données locale sera créé par les 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

Les migrations spécifient explicitement des noms pour les colonnes et les tables lorsqu’elles structurent une migration. 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 ce qui suit :

Si vous avez utilisé « Option 1 : Utiliser le schéma existant comme point de départ » à l’étape 3 :

  • Si les modifications futures de votre modèle nécessitent la modification ou la suppression d’un des objets de base de données nommés différemment, vous devez modifier la migration automatique 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 Post 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, rétablir une base de données vide) sur votre base de données locale peut échouer, car les migrations essaieront de supprimer des index et des contraintes de clé étrangère à l’aide des noms incorrects. Cela affecte uniquement votre base de données locale, car d’autres bases de données sont créées à partir de zéro à l’aide de 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 ou en supprimant toutes les tables. Une fois que cette mise à niveau initiale de tous les objets de base de données sera recréée avec les noms par défaut, ce problème ne se présentera pas à nouveau.
  • 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, il fonctionne 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 recréer votre base de données à partir de zéro, comme sur d’autres ordinateurs.
  • Les bases de données créées à l’aide de 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 les 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 ce qui suit :

  • 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 savent pas effectuer ces modifications. Par exemple, si vous supprimez une colonne qui a un index supplémentaire sur celui-ci, migrations ne sait pas supprimer l’index. Vous devez l’ajouter manuellement à la migration générée automatiquement.
  • Si vous avez utilisé « Option Two : Utiliser une base de données vide comme point de départ », ces objets supplémentaires ne seront pas créés par 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 des SQL brutes pour les créer/les supprimer.