Partage via


Amorçage des données

L’amorçage des données est le processus de remplissage d’une base de données avec un ensemble initial de données.

Il existe plusieurs façons d’effectuer cette opération dans EF Core :

  • Données initiales du modèle
  • Personnalisation manuelle de la migration
  • Logique d’initialisation personnalisée

Données initiales du modèle

Contrairement à EF6, dans EF Core, les données d’amorçage peuvent être associées à un type d’entité dans le cadre de la configuration du modèle. Les migrations EF Core peuvent alors automatiquement calculer les opérations d’insertion, de mise à jour ou de suppression à appliquer au moment de la mise à niveau de la base de données vers une nouvelle version du modèle.

Remarque

Les migrations considèrent uniquement les modifications de modèle lors de la détermination de l’opération à effectuer pour obtenir les données initiales dans l’état souhaité. Ainsi, les modifications apportées aux données effectuées en dehors des migrations peuvent être perdues ou provoquer une erreur.

Par exemple, cette opération configure les données initiales d’un Blog dans OnModelCreating :

modelBuilder.Entity<Blog>().HasData(new Blog { BlogId = 1, Url = "http://sample.com" });

Pour ajouter des entités qui ont une relation, les valeurs de clé étrangère doivent être spécifiées :

modelBuilder.Entity<Post>().HasData(
    new Post { BlogId = 1, PostId = 1, Title = "First post", Content = "Test 1" });

Si le type d’entité possède des propriétés dans un état d’ombre, une classe anonyme peut être utilisée pour fournir les valeurs :

modelBuilder.Entity<Post>().HasData(
    new { BlogId = 1, PostId = 2, Title = "Second post", Content = "Test 2" });

Les types d’entités détenus peuvent être amorcés de la même manière :

modelBuilder.Entity<Post>().OwnsOne(p => p.AuthorName).HasData(
    new { PostId = 1, First = "Andriy", Last = "Svyryd" },
    new { PostId = 2, First = "Diego", Last = "Vega" });

Pour plus de contexte, consultez l’exemple de projet complet.

Une fois les données ajoutées au modèle, les migrations doivent être utilisées pour appliquer les modifications.

Conseil

Si vous devez appliquer des migrations dans le cadre d’un déploiement automatisé, vous pouvez créer un script SQL qui peut être prévisualisé avant l’exécution.

Vous pouvez également utiliser context.Database.EnsureCreated() pour créer une base de données contenant les données initiales, par exemple pour une base de données de test ou lors de l’utilisation du fournisseur en mémoire ou d’une base de données non relationnelle. Notez que si la base de données existe déjà, EnsureCreated() n’effectue aucune mise à jour du schéma ni amorçage des données dans la base de données. Pour les bases de données relationnelles, vous ne devez pas appeler EnsureCreated() si vous envisagez d’utiliser des migrations.

Limitations des données initiales du modèle

Ce type de données initiales est géré par des migrations et le script pour mettre à jour les données qui se trouvent déjà dans la base de données doit être généré sans se connecter à la base de données. Cela impose certaines restrictions :

  • La valeur de clé primaire doit être spécifiée même si elle est généralement générée par la base de données. Elle sera utilisée pour détecter les modifications de données entre les migrations.
  • Les données précédemment amorcées sont supprimées si la clé primaire est modifiée de quelque manière que ce soit.

Par conséquent, cette fonctionnalité est la plus utile pour les données statiques qui ne sont pas censées changer en dehors des migrations et ne dépendent de rien d’autre dans la base de données, par exemple des codes ZIP.

Si votre scénario inclut l’une des opérations suivantes, il est recommandé d’utiliser la logique d’initialisation personnalisée décrite dans la dernière section :

  • Données temporaires pour les tests
  • Données qui dépendent de l’état de la base de données
  • Données volumineuses (les données d’amorçage sont capturées dans les instantanés de migration, et les données volumineuses peuvent rapidement entraîner des fichiers volumineux et des performances dégradées).
  • Données nécessitant des valeurs de clé générées par la base de données, y compris les entités qui utilisent des clés alternatives comme identité
  • Données nécessitant une transformation personnalisée (qui n’est pas gérée par des conversions de valeurs), telles que le hachage de mot de passe
  • Données nécessitant des appels à une API externe, telles que les rôles d’identité et la création d’utilisateurs ASP.NET Core

Personnalisation manuelle de la migration

Lorsqu’une migration est ajoutée, les modifications apportées aux données spécifiées avec HasData sont transformées en appels vers InsertData(), UpdateData() et DeleteData(). Une façon de contourner certaines des limitations de HasData consiste à ajouter manuellement ces appels ou opérations personnalisées à la migration à la place.

migrationBuilder.InsertData(
    table: "Blogs",
    columns: new[] { "Url" },
    values: new object[] { "http://generated.com" });

Logique d’initialisation personnalisée

Un moyen simple et puissant d’effectuer l’amorçage des données consiste à utiliser DbContext.SaveChanges() avant que la logique d’application principale commence l’exécution.

using (var context = new DataSeedingContext())
{
    context.Database.EnsureCreated();

    var testBlog = context.Blogs.FirstOrDefault(b => b.Url == "http://test.com");
    if (testBlog == null)
    {
        context.Blogs.Add(new Blog { Url = "http://test.com" });
    }

    context.SaveChanges();
}

Avertissement

Le code d’amorçage ne doit pas faire partie de l’exécution normale de l’application, car cela peut entraîner des problèmes d’accès concurrentiel lorsque plusieurs instances sont en cours d’exécution et nécessiterait également que l’application ait l’autorisation de modifier le schéma de la base de données.

Selon les contraintes de votre déploiement, le code d’initialisation peut être exécuté de différentes façons :

  • Exécution locale de l’application d’initialisation
  • Déploiement de l’application d’initialisation avec l’application principale, avec un appel de la routine d’initialisation et la désactivation ou suppression de l’application d’initialisation.

Cela peut généralement être automatisé à l’aide de profils de publication.