Gestion des migrations

À mesure que votre modèle change, les migrations sont ajoutées et supprimées dans le cadre d’un développement normal, et les fichiers de migration sont archivés dans le contrôle de code source de votre projet. Pour gérer les migrations, vous devez d’abord installer les outils en ligne de commande EF Core.

Conseil

Si DbContext se trouve dans un assembly différent du projet de démarrage, vous pouvez spécifier explicitement les projets cible et de démarrage dans les outils de la console du gestionnaire de package ou dans les outils CLI .NET Core.

Ajouter une migration

Une fois votre modèle modifié, vous pouvez ajouter une migration pour cette modification :

dotnet ef migrations add AddBlogCreatedTimestamp

Le nom de la migration peut être utilisé comme un message de validation dans un système de gestion de versions. Par exemple, vous pouvez choisir un nom comme AddBlogCreatedTimestamp si la modification est une nouvelle CreatedTimestamp propriété sur votre Blog entité.

Trois fichiers sont ajoutés à votre projet sous le répertoire Migrations :

  • XXXXXXXXXXXXXX_AddCreatedTimestamp.cs : fichier principal des migrations. Contient les opérations nécessaires à l’application de la migration (dans Up) et à sa restauration (dans Down).
  • XXXXXXXXXXXXXX_AddCreatedTimestamp.Designer.cs : fichier de métadonnées migrations. Contient des informations utilisées par EF.
  • MyContextModelSnapshot.cs : instantané de votre modèle actuel. Permet de déterminer ce qui a changé pendant l’ajout de la migration suivante.

L’horodatage dans le nom des fichiers permet de conserver ces derniers dans l’ordre chronologique et de voir ainsi la progression des modifications.

Espaces de noms

Vous êtes libre de déplacer les fichiers Migrations et de changer leur espace de noms manuellement. Les migrations sont créées en tant que sœurs de la dernière migration. Vous pouvez également spécifier le répertoire au moment de la génération comme suit :

dotnet ef migrations add InitialCreate --output-dir Your/Directory

Notes

Vous pouvez également modifier l’espace de noms indépendamment du répertoire à l’aide --namespacede .

Personnaliser le code de migration

Bien qu’EF Core crée généralement des migrations précises, vous devez toujours passer en revue le code et vous assurer qu’il correspond à la modification souhaitée ; dans certains cas, il est même nécessaire de le faire.

Renommages de colonnes

Un exemple notable où la personnalisation des migrations est nécessaire est lors du changement de nom d’une propriété. Par exemple, si vous renommez une propriété à , NameFullNameEF Core génère la migration suivante :

migrationBuilder.DropColumn(
    name: "Name",
    table: "Customers");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customers",
    nullable: true);

EF Core ne peut généralement pas savoir quand l’intention est de supprimer une colonne et d’en créer une nouvelle (deux modifications distinctes), et quand une colonne doit être renommée. Si la migration ci-dessus est appliquée en l’état, tous les noms de vos clients seront perdus. Pour renommer une colonne, remplacez la migration générée ci-dessus par les éléments suivants :

migrationBuilder.RenameColumn(
    name: "Name",
    table: "Customers",
    newName: "FullName");

Conseil

Le processus de structuration de migration vous avertit quand une opération peut entraîner une perte de données (par exemple la suppression d’une colonne). Si cet avertissement s’affiche, veillez particulièrement à examiner si le code de migration est exact.

Ajout de SQL brut

Bien que le renommage d’une colonne puisse être obtenu via une API intégrée, dans de nombreux cas, ce n’est pas possible. Par exemple, nous pouvons remplacer les propriétés et LastName existantes FirstName par une nouvelle propriété uniqueFullName. La migration générée par EF Core sera la suivante :

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

Comme auparavant, cela entraînerait une perte de données indésirable. Pour transférer les données à partir des anciennes colonnes, nous réorganisons les migrations et introduisons une opération SQL brute comme suit :

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

migrationBuilder.Sql(
@"
    UPDATE Customer
    SET FullName = FirstName + ' ' + LastName;
");

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

Modifications arbitraires via SQL brut

Sql brut peut également être utilisé pour gérer des objets de base de données dont EF Core n’a pas connaissance. Pour ce faire, ajoutez une migration sans modifier le modèle ; une migration vide est générée, que vous pouvez ensuite remplir avec des opérations SQL brutes.

Par exemple, la migration suivante crée une procédure stockée SQL Server :

migrationBuilder.Sql(
@"
    EXEC ('CREATE PROCEDURE getFullName
        @LastName nvarchar(50),
        @FirstName nvarchar(50)
    AS
        RETURN @LastName + @FirstName;')");

Conseil

EXEC est utilisé lorsqu’une instruction doit être la première ou la seule dans un lot SQL. Il peut également être utilisé pour contourner les erreurs de l’analyseur dans les scripts de migration idempotents qui peuvent se produire lorsque les colonnes référencées n’existent pas actuellement sur une table.

Cela peut être utilisé pour gérer n’importe quel aspect de votre base de données, notamment :

  • Procédures stockées
  • Recherche en texte intégral
  • Fonctions
  • Déclencheurs
  • Vues

Dans la plupart des cas, EF Core enveloppe automatiquement chaque migration dans sa propre transaction lors de l’application de migrations. Malheureusement, certaines opérations de migration ne peuvent pas être effectuées dans une transaction dans certaines bases de données ; dans ce cas, vous pouvez refuser la transaction en passant suppressTransaction: true à migrationBuilder.Sql.

Supprimer une migration

Parfois, vous ajoutez une migration et réalisez que vous devez apporter des modifications supplémentaires à votre modèle EF Core avant de l’appliquer. Pour supprimer la dernière migration, utilisez cette commande.

dotnet ef migrations remove

Après avoir supprimé la migration, vous pouvez apporter les modifications supplémentaires au modèle et la rajouter.

Avertissement

Évitez de supprimer les migrations qui ont déjà été appliquées aux bases de données de production. Cela signifie que vous ne pourrez pas rétablir ces migrations à partir des bases de données et que vous risquez d’annuler les hypothèses formulées par les migrations suivantes.

Liste des migrations

Vous pouvez répertorier toutes les migrations existantes comme suit :

dotnet ef migrations list

Réinitialiser toutes les migrations

Dans certains cas extrêmes, il peut être nécessaire de supprimer toutes les migrations et de recommencer. Pour ce faire, vous pouvez facilement supprimer votre dossier Migrations et supprimer votre base de données ; à ce stade, vous pouvez créer une migration initiale, qui contiendra l’ensemble de votre schéma actuel.

Il est également possible de réinitialiser toutes les migrations et d’en créer une seule sans perdre vos données. Cela est parfois appelé « squashing », et implique un travail manuel :

  • Supprimer votre dossier Migrations
  • Créer une migration et générer un script SQL pour celle-ci
  • Dans votre base de données, supprimez toutes les lignes de la table d’historique des migrations
  • Insérez une seule ligne dans l’historique des migrations pour enregistrer que la première migration a déjà été appliquée, car vos tables sont déjà là. L’insertion SQL est la dernière opération du script SQL générée ci-dessus.

Avertissement

Tout code de migration personnalisé est perdu lorsque le dossier Migrations est supprimé. Toutes les personnalisations doivent être appliquées manuellement à la nouvelle migration initiale afin d’être conservées.

Ressources supplémentaires