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 en particulier et ignorer la configuration qui n’est pas prise en charge ou qui n’est pas applicable. Pour plus d’informations sur la configuration spécifique du fournisseur, consultez la section Fournisseurs de base de données.
Conseil
Vous pouvez afficher les exemples de cet article sur GitHub.
Utiliser l’API Fluent pour configurer un modèle
Vous pouvez substituer la méthode OnModelCreating
dans le contexte dérivé et utiliser l’API Fluent pour configurer votre modèle. Il s’agit de la méthode de configuration la plus puissante, qui permet de spécifier une configuration sans modifier les classes d’entité. Dotée du niveau de priorité le plus élevé, la configuration de l’API Fluent 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
Pour appliquer la même configuration à plusieurs objets du modèle, consultez Configuration en bloc.
Configuration du regroupement
Pour réduire la taille de la méthode OnModelCreating
, 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 méthode Configure
à partir de OnModelCreating
.
new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());
Appliquer 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’est pas important.
Utiliser EntityTypeConfigurationAttribute
sur les types d’entités
Au lieu d’appeler Configure
explicitement, 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 IEntityTypeConfiguration
spécifiée chaque fois que le type d’entité Book
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 propriété DbSet<TEntity> 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
les types EntityTypeConfigurationAttribute
ne seront pas détectés automatiquement dans un assembly. 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 des attributs (également appelés annotations de données) à vos classes et propriétés. Les annotations de données remplacent les conventions, mais elles 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 comprend 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 prêt à l’emploi.
Conseil
Le code indiqué ci-dessous provient de ModelBuildingConventionsSample.cs.
Supprimer 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
Si votre modèle n’utilise pas d’attributs de mappage (ou annotations de données) pour la configuration, toutes les conventions portant le nom se terminant par AttributeConvention
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 de clé étrangère
Il est généralement judicieux de créer des index pour les colonnes de clé étrangère (FK) ; il existe donc 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 Blog
et Author
, nous pouvons voir que deux index sont créés : un pour la FK BlogId
, et l’autre pour la FK AuthorId
.
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, vous pouvez supprimer ForeignKeyIndexConvention
lors de la génération du modèle :
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}
Désormais, en examinant la vue de débogage du modèle pour Post
, nous voyons que les index sur les 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
Lorsque vous le souhaitez, les index peuvent toujours être créés explicitement pour les colonnes de clé étrangère, soit à l’aide de l’IndexAttribute ou via 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 :
Elle 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. La forme longue contient également toutes les annotations, qui peuvent être utiles si vous devez afficher les métadonnées relationnelles ou spécifiques au fournisseur. La vue longue est également accessible à partir du code :
Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));