Migrations dans les environnements d’équipe

Lorsque vous travaillez avec des migrations dans des environnements d’équipe, différents problèmes peuvent survenir lorsque des migrations sont ajoutées par plusieurs développeurs en même temps ; Notez que les migrations ne sont pas simplement des scripts SQL, mais incluent également un instantané du modèle au moment de cette migration.

Par exemple, imaginez que le développeur A et B créent des branches de travail en même temps et génèrent une migration dans leurs branches. Si le développeur A fusionne sa branche, puis que le développeur B effectue la même opération, la dernière migration (développeur B) a un instantané de contexte qui n’inclut pas les modifications apportées à la migration du développeur A. Cela peut entraîner diverses formes de corruption dans les migrations ultérieures.

Par conséquent, il est vivement recommandé de coordonner à l’avance et d’éviter de travailler simultanément sur les migrations dans plusieurs branches lorsque cela est possible.

Les migrations forment une séquence ordonnée. Les métadonnées du concepteur de chaque migration représentent le modèle à ce stade de la séquence et sont utilisées lors de la suppression de la migration. Ne résolvez pas les migrations parallèles en triant ou en renommant leurs fichiers : la migration ultérieure contiendrait toujours des métadonnées qui n’incluent pas les modifications de l’autre branche.

Détection des arborescences de migration divergentes

Note

Cette fonctionnalité est introduite dans EF Core 11 à partir de la préversion-3.

À compter d’EF 11, l’instantané de modèle enregistre l’ID de la migration la plus récente. Cela signifie que si deux développeurs créent chacune une migration sur des branches distinctes, la fusion de ces branches génère un conflit de contrôle de code source dans le fichier d’instantané de modèle, car les deux branches modifient l’ID de migration le plus récent. Ce conflit est un signal important : il vous indique que les arbres de migration ont divergé, et l’un d’entre eux doit être éliminé avant de continuer.

Pour résoudre ce problème, suivez les étapes de résolution des arborescences de migration divergentes ci-dessous : abandonnez la fusion, supprimez votre migration (en conservant les modifications de votre modèle), fusionnez les modifications de votre collègue, puis rajoutez votre migration.

EF Core 10 et versions antérieures n’enregistrent pas l’ID de migration le plus récent dans l’instantané du modèle. Par conséquent, un système de contrôle de code source peut fusionner l’instantané sans signaler ce conflit. Les arborescences de migration sont toujours divergentes et doivent être résolues à l’aide du même flux de travail.

Résolution des arborescences de migration divergentes

Si, lors de la fusion d’une branche, une arborescence de migration divergente est détectée, résolvez-la en recréant votre migration. Suivez ces étapes :

  1. Abandonnez la fusion et revenez à votre répertoire de travail avant la fusion.
  2. Supprimez votre migration, mais conservez les modifications apportées au modèle qui l’ont produite. Le contrôle de code source peut être utilisé pour supprimer uniquement les fichiers de migration générés et restaurer l’instantané de prémigration.
  3. Fusionnez les modifications de votre collègue dans votre répertoire de travail.
  4. Ajoutez de nouveau votre migration afin qu’elle soit basée sur l’instantané du modèle fusionné.

Après cela, votre migration est correctement basée sur toutes les migrations qui ont été ajoutées dans l’autre branche, et son instantané de contexte contient toutes les modifications précédentes. Votre migration peut désormais être partagée en toute sécurité avec le reste de l’équipe.

N’exécutez pas dotnet ef migrations remove (ou Remove-Migration) une fois que les migrations parallèles ont déjà été fusionnées en une séquence non valide. La commande restaure le modèle représenté par les métadonnées du concepteur de la migration précédente, qui peuvent ne pas contenir les modifications de l’autre branche. Utilisez le contrôle de code source pour revenir à un état de pré-fusion cohérent, puis suivez les étapes ci-dessus.

Annuler les modifications de migration dans la gestion de code source

Annuler un commit dans le contrôle de version ne modifie aucune base de données. Avant de supprimer le code de migration, choisissez l’une des approches suivantes :

  • Si la migration n’a pas été appliquée à une base de données partagée, supprimez la migration, puis rétablissez les modifications du modèle.
  • Si la migration a été appliquée, migrez la base de données vers une migration antérieure pendant que le code de migration est toujours disponible ou déployez une nouvelle migration corrective. Maintenez le déploiement d’applications et de bases de données compatibles tout au long de la restauration.

Ne supprimez pas la source de migration qui est toujours enregistrée dans une base de données partagée. Si le code a déjà été annulé, extrayez ou restaurez le commit contenant la migration afin de générer et de tester le retour en arrière, puis validez une séquence de migrations cohérente.

Passer en revue et valider les scripts de migration

Les déploiements en production nécessitent souvent une approbation des modifications du schéma. Au lieu d’appliquer directement des migrations, générez le code SQL que EF Core exécuterait et exécutez-le via le même processus de révision que d’autres modifications.

Générez le script pour révision dans CI :

dotnet ef migrations script --idempotent -o artifacts/migrate.sql

Notez que les scripts idempotents dépendent de la prise en charge du fournisseur. Par exemple, SQLite ne prend actuellement pas en charge la génération de ces éléments ; dans ce cas, générez une paire de scripts avec version à la place.

Utilisez Azure DevOps validations et contrôles (ou l’équivalent dans votre système d’intégration continue) pour bloquer le déploiement jusqu’à ce qu’un réviseur approuve le code SQL exact :

stages:
- stage: generate
  jobs:
  - job: build
    steps:
    - script: dotnet ef migrations script --idempotent -o $(Build.ArtifactStagingDirectory)/migrate.sql
      displayName: Generate migration script
    - script: dotnet ef migrations script PreviousMigration Latest -o $(Build.ArtifactStagingDirectory)/rollback.sql
      displayName: Generate rollback script
    - publish: $(Build.ArtifactStagingDirectory)
      artifact: sql

- stage: review
  jobs:
  - deployment: signoff
    environment: dba-review
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: sql
          - script: echo "Review migrate.sql and rollback.sql in $(Pipeline.Workspace)/sql"

- stage: deploy
  jobs:
  - deployment: apply
    environment: production
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: sql
          - script: sqlcmd -i "$(Pipeline.Workspace)/sql/migrate.sql"
            displayName: Apply the approved script

Déployez le script révisé lui-même plutôt que de régénérer SQL au moment du déploiement, de sorte que les réviseurs approuvent les opérations exactes qui s’exécutent.

Scripts de restauration

Dans dotnet ef migrations script, from décrit l’état initial de la base de données et to l’état cible ; à la place, un from plus récent que to génère les opérations de Down des migrations. Générez un script de restauration à partir de l’état de migration actuel (plus récent) vers une cible antérieure et stockez-le en regard du script de transfert.

Warning

Un script de restauration exécute les opérations des Down migrations, mais il ne peut généralement pas reconstruire les données supprimées ou transformées par la migration vers l’avant. Testez le retour en arrière sur une copie du schéma de production et examinez les répercussions sur les données avant de vous y fier.