Amorçage des donnéesData Seeding

L’amorçage des données est le processus de remplissage d’une base de données avec un ensemble initial de données.Data seeding is the process of populating a database with an initial set of data.

Il existe plusieurs façons qu'y parvenir dans EF Core :There are several ways this can be accomplished in EF Core:

  • Données d’amorçage de modèleModel seed data
  • Personnalisation d’une migration manuelleManual migration customization
  • Logique d’initialisation personnaliséCustom initialization logic

Données d’amorçage de modèleModel seed data

Note

Cette fonctionnalité est une nouveauté d’EF Core 2.1.This feature is new in EF Core 2.1.

Contrairement à dans EF6, dans EF Core, l’amorçage des données peut être associé à un type d’entité dans le cadre de la configuration du modèle.Unlike in EF6, in EF Core, seeding data can be associated with an entity type as part of the model configuration. Puis EF Core migrations peut calculer automatiquement les éléments insérant, mettre à jour ou supprimer la nécessité d’opérations à appliquer lors de la mise à niveau de la base de données vers une nouvelle version du modèle.Then EF Core migrations can automatically compute what insert, update or delete operations need to be applied when upgrading the database to a new version of the model.

Note

Migrations considère uniquement les modifications apportées au modèle pour déterminer quelle opération doit être effectuée pour obtenir les données d’amorçage dans l’état souhaité.Migrations only considers model changes when determining what operation should be performed to get the seed data into the desired state. Par conséquent, les modifications apportées aux données effectuées en dehors de migrations peuvent être perdues ou provoquer une erreur.Thus any changes to the data performed outside of migrations might be lost or cause an error.

Par exemple, cette opération configure les données d’amorçage pour un Blog dans OnModelCreating:As an example, this will configure seed data for a Blog in OnModelCreating:

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

Pour ajouter des entités ayant une relation de valeurs de clés étrangères doivent être spécifiés :To add entities that have a relationship the foreign key values need to be specified:

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

Si le type d’entité a des propriétés dans l’état de clichés instantanés qu'une classe anonyme peut être utilisée pour fournir les valeurs :If the entity type has any properties in shadow state an anonymous class can be used to provide the values:

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

Détenues entité types peuvent être exécutées de manière similaire :Owned entity types can be seeded in a similar fashion:

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

Consultez le exemple complet de projet pour plus de contexte.See the full sample project for more context.

Une fois que les données ont été ajoutées au modèle, migrations doit être utilisé pour appliquer les modifications.Once the data has been added to the model, migrations should be used to apply the changes.

Conseil

Si vous avez besoin appliquer des migrations en tant que partie d’un déploiement automatisé, vous pouvez créer un script SQL qui peuvent être visualisés avant l’exécution.If you need to apply migrations as part of an automated deployment you can create a SQL script that can be previewed before execution.

Vous pouvez également utiliser context.Database.EnsureCreated() pour créer une nouvelle base de données contenant les données d’amorçage, par exemple pour une base de données de test ou lorsque vous utilisez le fournisseur en mémoire ou une base de données non-relation.Alternatively, you can use context.Database.EnsureCreated() to create a new database containing the seed data, for example for a test database or when using the in-memory provider or any non-relation database. Notez que si la base de données existe déjà, EnsureCreated() sera ni mettre à jour les données de schéma ni de valeur initiale dans la base de données.Note that if the database already exists, EnsureCreated() will neither update the schema nor seed data in the database. Pour les bases de données relationnelles vous ne devez pas appeler EnsureCreated() si vous envisagez d’utiliser des Migrations.For relational databases you shouldn't call EnsureCreated() if you plan to use Migrations.

Ce type de données d’amorçage est géré par des migrations et le script pour mettre à jour les données qui se trouve déjà dans la base de données doit être généré sans vous connecter à la base de données.This type of seed data is managed by migrations and the script to update the data that's already in the database needs to be generated without connecting to the database. Cela impose certaines restrictions :This imposes some restrictions:

  • La valeur de clé primaire doit être spécifié même s’il est généralement généré par la base de données.The primary key value needs to be specified even if it's usually generated by the database. Il sera utilisé pour détecter des modifications de données entre des migrations.It will be used to detect data changes between migrations.
  • Les données de départ seront supprimées si la clé primaire est modifiée en aucune façon.Previously seeded data will be removed if the primary key is changed in any way.

Par conséquent, cette fonctionnalité est particulièrement utile pour les données statiques qui n’a pas censé modifier en dehors des migrations et ne repose pas sur rien d’autre dans la base de données, par exemple les codes postaux.Therefore this feature is most useful for static data that's not expected to change outside of migrations and does not depend on anything else in the database, for example ZIP codes.

Si votre scénario comprend les éléments suivants, il est recommandé d’utiliser la logique d’initialisation personnalisé décrite dans la dernière section :If your scenario includes any of the following it is recommended to use custom initialization logic described in the last section:

  • Données temporaires pour le testTemporary data for testing
  • Données qui varie selon l’état de la base de donnéesData that depends on database state
  • Données dont a besoin des valeurs de clé devant être généré par la base de données, y compris les entités qui utilisent des clés secondaires en tant que l’identitéData that needs key values to be generated by the database, including entities that use alternate keys as the identity
  • Les données qui nécessite une transformation personnalisée (qui n’est pas gérée par valeur conversions), par exemple un hachage de mot de passeData that requires custom transformation (that is not handled by value conversions), such as some password hashing
  • Données qui nécessite des appels d’API externe, telle que la création des rôles et les utilisateurs de ASP.NET Core IdentityData that requires calls to external API, such as ASP.NET Core Identity roles and users creation

Personnalisation d’une migration manuelleManual migration customization

Lorsqu’une migration est ajoutée les modifications apportées aux données spécifiées avec HasData sont transformées en appels à InsertData(), UpdateData(), et DeleteData().When a migration is added the changes to the data specified with HasData are transformed to calls to InsertData(), UpdateData(), and DeleteData(). Une façon de contourner certaines des limitations de HasData consiste à ajouter manuellement ces appels ou opérations personnalisées pour la migration à la place.One way of working around some of the limitations of HasData is to manually add these calls or custom operations to the migration instead.

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

Logique d’initialisation personnaliséCustom initialization logic

Un moyen simple et puissant pour effectuer l’amorçage des données consiste à utiliser DbContext.SaveChanges() avant le principal de l’application logique commence à s’exécuter.A straightforward and powerful way to perform data seeding is to use DbContext.SaveChanges() before the main application logic begins execution.

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 être de partie de l’exécution d’application normal car cela peut provoquer des problèmes d’accès concurrentiel lorsque plusieurs instances sont en cours d’exécution et qu’il nécessitent également l’application ayant l’autorisation de modifier le schéma de base de données.The seeding code should not be part of the normal app execution as this can cause concurrency issues when multiple instances are running and would also require the app having permission to modify the database schema.

Selon les contraintes de votre déploiement, le code d’initialisation peut être exécuté de différentes façons :Depending on the constraints of your deployment the initialization code can be executed in different ways:

  • Exécution de l’application de l’initialisation localementRunning the initialization app locally
  • Déploiement de l’application de l’initialisation avec l’application principale, l’appel de la routine d’initialisation et la désactivation ou la suppression de l’application de l’initialisation.Deploying the initialization app with the main app, invoking the initialization routine and disabling or removing the initialization app.

Cette tâche peut généralement être automatisée à l’aide de profils de publication.This can usually be automated by using publish profiles.