Erstellen und Konfigurieren eines Modells
EF Core verwendet eine Metadatenmodell, um zu beschreiben, wie die Entitätstypen der Anwendung der zugrunde liegenden Datenbank zugeordnet werden. Dieses Modell wird mit einer Reihe von Konventionen erstellt, also Heuristiken, die nach häufigen Mustern suchen. Dieses Modell kann mithilfe von Zuordnungsattributen (auch als Datenanmerkungen) und/oder Aufrufen der ModelBuilder-Methoden (auch als Fluent-API) in OnModelCreating angepasst werden. Beide setzen die durch Konventionen ausgeführte Konfiguration außer Kraft.
Die meisten Konfigurationen können auf ein Modell angewendet werden, das auf einen beliebigen Datenspeicher ausgerichtet ist. Anbieter können auch eine Konfiguration ermöglichen, die für einen bestimmten Datenspeicher spezifisch ist, und sie können auch die Konfiguration ignorieren, die nicht unterstützt oder nicht zutreffend ist. Eine Dokumentation zu anbieterspezifischen Konfigurationen finden Sie im Abschnitt Datenbankanbieter.
Tipp
Die in diesem Artikel verwendeten Beispiele finden Sie auf GitHub.
Verwenden der Fluent-API zum Konfigurieren eines Modells
Sie können die OnModelCreating
-Methode in Ihrem abgeleiteten Kontext außer Kraft setzen und mit der Fluent-API Ihr Modell konfigurieren. Dies ist die wirksamste Konfigurationsmethode und erlaubt die Angabe der Konfiguration, ohne die Entitätsklassen zu verändern. Die Fluent-API-Konfiguration hat die höchste Priorität und überschreibt Konventionen und Datenanmerkungen. Die Konfiguration wird in der Reihenfolge angewendet, in der die Methoden aufgerufen werden, und wenn Konflikte auftreten, setzt der neueste Aufruf die zuvor angegebene Konfiguration außer Kraft.
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; }
}
Tipp
Informationen zum Anwenden derselben Konfiguration auf mehrere Objekte im Modell finden Sie unter Massenkonfiguration.
Gruppieren der Konfiguration
Um die Größe der OnModelCreating
-Methode zu reduzieren, kann die gesamte Konfiguration für einen Entitätstyp in eine separate Klasse extrahiert werden, indem IEntityTypeConfiguration<TEntity> implementiert wird.
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder
.Property(b => b.Url)
.IsRequired();
}
}
Rufen Sie dann einfach die Configure
-Methode aus OnModelCreating
auf.
new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());
Anwenden aller Konfigurationen in einer Assembly
Es ist möglich, sämtliche Konfigurationen anzuwenden, die in Typen angegeben werden, indem IEntityTypeConfiguration
in einer bestimmten Assembly implementiert wird.
modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);
Hinweis
Die Reihenfolge, in der die Konfigurationen angewendet werden, ist nicht definiert. Diese Methode sollte daher nur verwendet werden, wenn die Reihenfolge keine Rolle spielt.
Verwenden von EntityTypeConfigurationAttribute
für Entitätstypen
Anstatt explizit Configure
aufzurufen, kann stattdessen EntityTypeConfigurationAttribute für den Entitätstyp festgelegt werden, sodass EF Core die entsprechende Konfiguration finden und verwenden kann. Beispiele:
[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Isbn { get; set; }
}
Dieses Attribut bedeutet, dass EF Core die angegebene IEntityTypeConfiguration
-Implementierung verwendet, wenn der Entitätstyp Book
in einem Modell enthalten ist. Der Entitätstyp wird dem Modell mit einem der gängigen Verfahren hinzugefügt, beispielsweise durch das Erstellen einer DbSet<TEntity>-Eigenschaft für den Entitätstyp:
public class BooksContext : DbContext
{
public DbSet<Book> Books { get; set; }
//...
Alternativ kann er bei OnModelCreating registriert werden:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>();
}
Hinweis
EntityTypeConfigurationAttribute
-Typen werden in einer Assembly nicht automatisch erkannt. Entitätstypen müssen dem Modell hinzugefügt werden, bevor das Attribut für diesen Entitätstyp erkannt wird.
Verwenden von Datenanmerkungen zum Konfigurieren eines Modells
Sie können auch bestimmte Attribute (sogenannte Datenanmerkungen) auf Ihre Klassen und Eigenschaften anwenden. Datenanmerkungen setzen Konventionen außer Kraft, werden aber ihrerseits von der Fluent-API-Konfiguration außer Kraft gesetzt.
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; }
}
Integrierte Konventionen
EF Core enthält viele Konventionen zum Erstellen von Modellen, die standardmäßig aktiviert sind. Sie finden alle in der Liste der Klassen, die die Schnittstelle IConvention implementieren. Diese Liste enthält jedoch keine Konventionen, die von Datenbankanbietern von Drittparteien und Plug-Ins eingeführt wurden.
Anwendungen können diese Konventionen entfernen oder ersetzen und neue benutzerdefinierte Konventionen hinzufügen, die Konfigurationen für Muster anwenden, die von EF nicht sofort erkannt werden.
Tipp
Der unten gezeigte Code stammt aus ModelBuildingConventionsSample.cs.
Entfernen einer vorhandenen Konvention
Manchmal ist eine der integrierten Konventionen für Ihre Anwendung möglicherweise nicht geeignet, in diesem Fall kann sie entfernt werden.
Tipp
Wenn Ihr Modell keine Zuordnungsattribute (auch als Datenanmerkungen bezeichnet) für die Konfiguration verwendet, können alle Konventionen mit dem Namen, der auf AttributeConvention
endet, sicher entfernt werden, um die Modellerstellung zu beschleunigen.
Beispiel: Erstellen Sie keine Indizes für Fremdschlüsselspalten.
Normalerweise ist es sinnvoll, Indizes für FK-Spalten (Fremdschlüsselspalten) zu erstellen. Daher gibt es hierfür eine integrierte Konvention: ForeignKeyIndexConvention. Wenn wir das Modell debug view (Debugansicht) für einen Post
-Entitätstyp mit Beziehungen zu Blog
und Author
betrachten, erkennen wir, dass zwei Indizes erstellt werden: einer für den Fremdschlüssel BlogId
und der andere für den Fremdschlüssel 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
Der Mehraufwand für Indizes ist jedoch höher, und es ist möglicherweise nicht immer geeignet, sie für alle FK-Spalten zu erstellen. Hierzu kann die ForeignKeyIndexConvention
-Klasse beim Erstellen des Modells entfernt werden:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}
In der Debugansicht des Modells für Post
sehen Sie jetzt, dass die Indizes für die FKs nicht erstellt wurden:
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
Bei Bedarf können Indizes weiterhin explizit für Fremdschlüsselspalten erstellt werden, entweder mithilfe der IndexAttribute oder mit Konfiguration in OnModelCreating
.
Debugansicht
Auf die Model Builder-Debugansicht kann im Debugger Ihrer IDE zugegriffen werden. Beispielsweise mit Visual Studio:
Es kann auch direkt über den Code auf sie zugegriffen werden, um beispielsweise die Debugansicht an die Konsole zu senden:
Console.WriteLine(context.Model.ToDebugString());
Die Debugansicht verfügt über ein kurzes Formular und ein langes Formular. Das lange Formular enthält auch alle Anmerkungen, die nützlich sein können, wenn Sie relationale oder anbieterspezifische Metadaten anzeigen müssen. Auf die lange Ansicht kann auch über den Code zugegriffen werden:
Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));