Partager via


Création et configuration d’un modèle

EF Core utilise un modèle de métadonnées pour décrire comment les types d’entités de l’application sont mappés à la base de données sous-jacente. Ce modèle est conçu à l’aide d’un ensemble de conventions - heuristiques qui recherchent des modèles courants. Le modèle peut ensuite être personnalisé à l’aide d’attributs de mappage (également appelés annotations de données) et/ou d’appels aux ModelBuilder méthodes (également appelées API Fluent) dans OnModelCreating, qui remplacent la configuration effectuée par des conventions.

La plupart des configurations peuvent être appliquées à un modèle ciblant n’importe quel magasin de données. Les fournisseurs peuvent également activer la configuration spécifique à un magasin de données particulier et ignorer la configuration qui n’est pas prise en charge ou non applicable. Pour obtenir de la documentation sur la configuration spécifique au fournisseur, consultez la section Fournisseurs de base de données .

Conseil / Astuce

Vous pouvez afficher les exemples de cet article sur GitHub.

Utiliser l’API Fluent pour configurer un modèle

Vous pouvez remplacer la OnModelCreating méthode dans votre contexte dérivé et utiliser l’API Fluent pour configurer votre modèle. Il s’agit de la méthode la plus puissante de configuration et permet de spécifier la configuration sans modifier vos classes d’entité. La configuration de l’API Fluent a la priorité la plus élevée et remplace les conventions et les annotations de données. La configuration est appliquée dans l’ordre dans lequel les méthodes sont appelées et en cas de conflit, le dernier appel remplace la configuration spécifiée précédemment.

using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.FluentAPI.Required;

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    #region Required
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .IsRequired();
    }
    #endregion
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Conseil / Astuce

Pour appliquer la même configuration à plusieurs objets du modèle, consultez la configuration en bloc.

Configuration du regroupement

Pour réduire la taille de la OnModelCreating méthode, toutes les configurations d’un type d’entité peuvent être extraites dans une classe distincte implémentant IEntityTypeConfiguration<TEntity>.

public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
    public void Configure(EntityTypeBuilder<Blog> builder)
    {
        builder
            .Property(b => b.Url)
            .IsRequired();
    }
}

Ensuite, appelez simplement la Configure méthode à partir de OnModelCreating.

new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());

Application de toutes les configurations dans un assembly

Il est possible d’appliquer toutes les configurations spécifiées dans les types implémentés IEntityTypeConfiguration dans un assembly donné.

modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);

Remarque

L’ordre dans lequel les configurations seront appliquées n’est pas défini. Par conséquent, cette méthode ne doit être utilisée que lorsque l’ordre n’a pas d’importance.

Utilisation EntityTypeConfigurationAttribute sur les types d’entités

Au lieu d’appeler Configureexplicitement, un EntityTypeConfigurationAttribute peut plutôt être placé sur le type d’entité afin qu’EF Core puisse rechercher et utiliser la configuration appropriée. Par exemple:

[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
}

Cet attribut signifie qu’EF Core utilisera l’implémentation spécifiée IEntityTypeConfiguration chaque fois que le Book type d’entité est inclus dans un modèle. Le type d’entité est inclus dans un modèle à l’aide de l’un des mécanismes normaux. Par exemple, en créant une DbSet<TEntity> propriété pour le type d’entité :

public class BooksContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    //...

Ou en l’inscrivant dans OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>();
}

Remarque

EntityTypeConfigurationAttribute les types ne seront pas découverts automatiquement dans un assemblage. Les types d’entités doivent être ajoutés au modèle avant que l’attribut soit découvert sur ce type d’entité.

Utiliser des annotations de données pour configurer un modèle

Vous pouvez également appliquer certains attributs (appelés Annotations de données) à vos classes et propriétés. Les annotations de données remplacent les conventions, mais sont remplacées par la configuration de l’API Fluent.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.DataAnnotations.Annotations;

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
}

[Table("Blogs")]
public class Blog
{
    public int BlogId { get; set; }

    [Required]
    public string Url { get; set; }
}

Conventions intégrées

EF Core inclut de nombreuses conventions de génération de modèles activées par défaut. Vous pouvez les trouver dans la liste des classes qui implémentent l’interface IConvention . Toutefois, cette liste n’inclut pas les conventions introduites par les fournisseurs de base de données tiers et les plug-ins.

Les applications peuvent supprimer ou remplacer l’une de ces conventions, ainsi que d’ajouter de nouvelles conventions personnalisées qui appliquent la configuration pour les modèles qui ne sont pas reconnus par EF hors de la boîte de dialogue.

Conseil / Astuce

Le code indiqué ci-dessous provient de ModelBuildingConventionsSample.cs.

Suppression d’une convention existante

Parfois, l’une des conventions intégrées peut ne pas convenir à votre application, auquel cas elle peut être supprimée.

Conseil / Astuce

Si votre modèle n’utilise pas d’attributs de mappage (alias annotations de données) pour la configuration, toutes les conventions portant le nom se terminant AttributeConvention par le nom peuvent être supprimées en toute sécurité pour accélérer la génération de modèles.

Exemple : Ne créez pas d’index pour les colonnes clés étrangères

Il est généralement judicieux de créer des index pour les colonnes de clé étrangère (FK), et par conséquent, il existe une convention intégrée pour ceci : ForeignKeyIndexConvention. En examinant la vue de débogage du modèle pour un type d’entité Post avec des relations avec Blog et Author, nous pouvons voir que deux index sont créés — un pour le BlogId FK, et l’autre pour le AuthorId FK.

  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      AuthorId (no field, int?) Shadow FK Index
      BlogId (no field, int) Shadow Required FK Index
    Navigations:
      Author (Author) ToPrincipal Author Inverse: Posts
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade
    Indexes:
      AuthorId
      BlogId

Toutefois, les index ont une surcharge et il peut ne pas toujours être approprié de les créer pour toutes les colonnes FK. Pour ce faire, le ForeignKeyIndexConvention peut être supprimé pendant la construction du modèle :

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}

En examinant la vue de débogage du modèle pour Post l’instant, nous voyons que les index sur les clés FK n’ont pas été créés :

  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      AuthorId (no field, int?) Shadow FK
      BlogId (no field, int) Shadow Required FK
    Navigations:
      Author (Author) ToPrincipal Author Inverse: Posts
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade

Lorsqu'ils le souhaitent, les index peuvent toujours être créés explicitement pour les colonnes de clé étrangère, soit en utilisant IndexAttribute, soit avec la configuration dans OnModelCreating.

Vue de débogage

La vue de débogage du générateur de modèles est accessible dans le débogueur de votre IDE. Par exemple, avec Visual Studio :

Accès à la vue de débogage du générateur de modèles à partir du débogueur Visual Studio

Il est également accessible directement à partir du code, par exemple pour envoyer la vue de débogage à la console.

Console.WriteLine(context.Model.ToDebugString());

La vue de débogage a une forme courte et une forme longue. Le formulaire long inclut également toutes les annotations, qui peuvent être utiles si vous devez afficher les métadonnées relationnelles ou spécifiques au fournisseur. La longue vue est également accessible à partir du code :

Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));