Gestion des migrations
À mesure que votre modèle change, les migrations sont ajoutées et supprimées dans le cadre du 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 tel que AddBlogCreatedTimestamp si la modification est une nouvelle propriété CreatedTimestamp
sur votre entité Blog
.
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 (dansDown
). - XXXXXXXXXXXXXX_AddCreatedTimestamp.Designer.cs : fichier de métadonnées des 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
Remarque
Vous pouvez également modifier l’espace de noms indépendamment du répertoire avec --namespace
.
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 colonne
L’un des exemples notables où la personnalisation des migrations est requise consiste à renommer une propriété. Par exemple, si vous renommez une propriété Name
en FullName
, EF Core génère la migration suivante :
migrationBuilder.DropColumn(
name: "Name",
table: "Customers");
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customers",
nullable: true);
EF Core est généralement incapable de savoir quand l’intention consiste à supprimer une colonne et à en créer une (deux modifications distinctes) et quand une colonne doit être renommée. Si la migration ci-dessus est appliquée telle qu’elle est, tous vos noms de 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 effectué via une API intégrée, dans de nombreux cas, ce n’est pas possible. Par exemple, nous souhaitons peut-être remplacer les propriétés existantes FirstName
et LastName
par une propriété FullName
unique et nouvelle. 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 précédemment, 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 les objets de base de données dont EF Core n’est pas conscient. Pour ce faire, ajoutez une migration sans apporter de modification de modèle ; une migration vide est générée, que vous pouvez ensuite remplir avec les 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ée lorsqu’une instruction doit être la première ou une seule dans un lot SQL. Elle peut aussi être utilisée pour contourner les erreurs d’analyseur dans les scripts de migration idempotents qui peuvent se produire lorsque des 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, y compris :
- Procédures stockées
- Recherche en texte intégral
- Functions
- Déclencheurs
- Les vues
Dans la plupart des cas, EF Core encapsule automatiquement chaque migration dans sa propre transaction lors de l’application des 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. Si vous faites cela, vous ne pourrez pas rétablir ces migrations à partir des bases de données et pourrez interrompre les hypothèses effectuées par les migrations suivantes.
Liste des migrations
Vous pouvez répertorier toutes les migrations existantes comme suit :
dotnet ef migrations list
Vérifier si des modifications de modèle sont en attente
Remarque
Cette fonctionnalité a été ajoutée dans EF Core 8.0.
Parfois, vous pourrez vouloir vérifier si des modifications ont été apportées au modèle depuis la dernière migration. Cela peut vous aider à savoir quand vous ou un collègue avez oublié d’ajouter une migration. Une des manières de le faire est d’utiliser cette commande.
dotnet ef migrations has-pending-model-changes
Vous pouvez également effectuer cette vérification par programmation à l’aide de context.Database.HasPendingModelChanges()
. Cela peut être utilisé pour écrire un test unitaire qui échoue lorsque vous oubliez d’ajouter une migration.
Réinitialisation de toutes les migrations
Dans certains cas extrêmes, il peut être nécessaire de supprimer toutes les migrations et de recommencer. Cette opération peut être facilement effectuée en supprimant votre dossier Migrations et en supprimant votre base de données ; à ce stade, vous pouvez créer une migration initiale qui contiendra l’intégralité 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. Ceci est parfois appelé une « action squash » et implique du travail manuel :
- Sauvegardez votre base de données, au cas où quelque chose se passe mal.
- Dans votre base de données, supprimez toutes les lignes de la table d’historique des migrations (p. ex.
DELETE FROM [__EFMigrationsHistory]
sur SQL Server). - Supprimez votre dossier Migrations.
- Créez une nouvelle migration et générez un script SQL pour celle-ci (
dotnet ef migrations script
). - 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 dans le script SQL généré ci-dessus et ressemble à ce qui suit (n’oubliez pas de mettre à jour les valeurs) :
INSERT INTO [__EFMigrationsHistory] ([MIGRATIONID], [PRODUCTVERSION])
VALUES (N'<full_migration_timestamp_and_name>', N'<EF_version>');
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
- Informations de référence sur les outils Entity Framework Core – .NET Core CLI : inclut des commandes permettant de mettre à jour, annuler, ajouter, supprimer, etc.
- Informations de référence sur les outils Entity Framework Core – Console du Gestionnaire de package dans Visual Studio : inclut des commandes permettant de mettre à jour, annuler, ajouter, supprimer, etc.