Einführung in Beziehungen

Dieses Dokument bietet eine einfache Einführung in die Darstellung von Beziehungen in Objektmodellen und relationalen Datenbanken, einschließlich der Zuordnung von EF Core zwischen den beiden.

Beziehungen in Objektmodellen

Eine Beziehung definiert, wie zwei Entitäten miteinander zusammenhängen. Wenn Sie beispielsweise Beiträge in einem Blog modellieren, ist jeder Beitrag mit dem Blog verknüpft, auf dem er veröffentlicht wird, und der Blog ist mit allen Beiträgen verknüpft, die in diesem Blog veröffentlicht wurden.

In einer objektorientierten Sprache wie C# werden der Blog und der Beitrag in der Regel durch zwei Klassen dargestellt: Blog und Post. Beispiel:

public class Blog
{
    public string Name { get; set; }
    public virtual Uri SiteUri { get; set; }
}
public class Post
{
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime PublishedOn { get; set; }
    public bool Archived { get; set; }
}

In den obigen Klassen gibt es nichts, um anzugeben, dass Blog und Post verwandt sind. Dies kann dem Objektmodell hinzugefügt werden, indem sie einen Verweis von Post auf Blog hinzufügen, wo es veröffentlicht ist:

public class Post
{
    public string Title { get; set; }
    public string Content { get; set; }
    public DateOnly PublishedOn { get; set; }
    public bool Archived { get; set; }

    public Blog Blog { get; set; }
}

Ebenso kann die entgegengesetzte Richtung der gleichen Beziehung als eine Sammlung von Post-Objekten auf jedem Blogdargestellt werden:

public class Blog
{
    public string Name { get; set; }
    public virtual Uri SiteUri { get; set; }

    public ICollection<Post> Posts { get; }
}

Diese Verbindung von Blog zu Post und umgekehrt von Post zurück zu Blog wird in EF Core als "Beziehung" bezeichnet.

Wichtig

Eine einzelne Beziehung kann in der Regel in beide Richtungen durchlaufen werden. In diesem Beispiel ist es von Blog zu Post über die Eigenschaft Blog.Posts und von Post zurück zu Blog über die Eigenschaft Post.Blog. Dies gilt als eine Beziehung, nicht als zwei.

Tipp

In EF Core werden die Eigenschaften Blog.Posts und Post.Blog als „Navigationselemente“ bezeichnet.

Beziehungen in relationalen Datenbanken

Relationale Datenbanken stellen Beziehungen mithilfe von Fremdschlüsseln dar. Mit SQL Server oder Azure SQL können beispielsweise die folgenden Tabellen verwendet werden, um unsere Klassen Post und Blog darzustellen:

CREATE TABLE [Posts] (
    [Id] int NOT NULL IDENTITY,
    [Title] nvarchar(max) NULL,
    [Content] nvarchar(max) NULL,
    [PublishedOn] datetime2 NOT NULL,
    [Archived] bit NOT NULL,
    [BlogId] int NOT NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]),
    CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blogs] ([Id]) ON DELETE CASCADE);

CREATE TABLE [Blogs] (
    [Id] int NOT NULL IDENTITY,
    [Name] nvarchar(max) NULL,
    [SiteUri] nvarchar(max) NULL,
    CONSTRAINT [PK_Blogs] PRIMARY KEY ([Id]));

In diesem relationalen Modell erhalten die Tabellen Posts und Blogs jeweils eine Spalte „Primärschlüssel“. Der Wert des Primärschlüssels identifiziert jeden Beitrag oder Blog eindeutig. Darüber hinaus erhält die Tabelle Posts eine Spalte „Fremdschlüssel“. Die Blogs-Primärschlüsselspalte Id wird von der Fremdschlüsselspalte BlogId der Tabelle Posts verwiesen. Diese Spalte ist „eingeschränkt“, sodass jeder Wert in der BlogId-Spalte von Posts einem Wert in der Spalte Id von Blogs übereinstimmen muss. Diese Übereinstimmung bestimmt, mit welchem Blog jeder Beitrag verknüpft ist. Wenn beispielsweise der Wert BlogId in einer Zeile der Tabelle Posts 7 ist, wird der Beitrag, der durch diese Zeile dargestellt wird, im Blog mit dem Primärschlüssel 7 veröffentlicht.

Zuordnen von Beziehungen in EF Core

Bei der EF Core-Beziehungszuordnung geht es um die Zuordnung der Primärschlüssel-/Fremdschlüsseldarstellung, die in einer relationalen Datenbank verwendet wird, mit den Verweisen zwischen Objekten, die in einem Objektmodell verwendet werden.

Im einfachsten Sinne umfasst dies Folgendes:

  • Hinzufügen einer Primärschlüsseleigenschaft zu jedem Entitätstyp.
  • Hinzufügen einer Fremdschlüsseleigenschaft zu einem Entitätstyp.
  • Zuordnen der Verweise zwischen Entitätstypen mit den Primär- und Fremdschlüsseln, um eine einzelne Beziehungskonfiguration zu bilden.

Sobald diese Zuordnung vorgenommen wurde, ändert EF die Fremdschlüsselwerte nach Bedarf, wenn sich die Verweise zwischen Objekten ändern, und ändert die Verweise zwischen Objekten nach Bedarf, wenn sich die Fremdschlüsselwerte ändern.

Hinweis

Primärschlüssel werden für mehr als die Zuordnung von Beziehungen verwendet. Weitere Informationen finden Sie unter Schlüssel.

Beispielsweise können die oben angezeigten Entitätstypen mit den Eigenschaften primärer und fremder Schlüssel aktualisiert werden:

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Uri SiteUri { get; set; }

    public ICollection<Post> Posts { get; }
}
public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime PublishedOn { get; set; }
    public bool Archived { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

Tipp

Primär- und Fremdschlüsseleigenschaften müssen nicht öffentlich sichtbare Eigenschaften des Entitätstyps sein. Selbst wenn die Eigenschaften ausgeblendet sind, ist es jedoch wichtig zu erkennen, dass sie noch im EF-Modell vorhanden sind.

Die Primärschlüsseleigenschaft von Blog, Blog.Id und die Fremdschlüsseleigenschaft von Post, Post.BlogId können dann den Verweisen ("Navigationen") zwischen den Entitätstypen (Blog.Posts und Post.Blog) verknüpft werden. Dies geschieht automatisch durch EF beim Erstellen einer einfachen Beziehung wie dieser, kann aber auch explizit angegeben werden, wenn die Methode OnModelCreating Ihrer Methode DbContext überschrieben wird. Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasMany(e => e.Posts)
        .WithOne(e => e.Blog)
        .HasForeignKey(e => e.BlogId)
        .HasPrincipalKey(e => e.Id);
}

Nun verhalten sich alle diese Eigenschaften kohärent zusammen als Darstellung einer einzelnen Beziehung zwischen Blog und Post.

Weitere Informationen

EF unterstützt viele verschiedene Arten von Beziehungen, mit vielen verschiedenen Möglichkeiten, wie diese Beziehungen dargestellt und konfiguriert werden können. Informationen zu Beispielen für verschiedene Arten von Beziehungen finden Sie unter:

  • 1:n-Beziehungen, in denen eine einzelne Entität einer beliebigen Anzahl anderer Entitäten zugeordnet ist.
  • 1:1-Beziehungen, bei denen eine einzelne Entität einer anderen einzelnen Entität zugeordnet ist.
  • M:n-Beziehungen, in denen eine beliebige Anzahl von Entitäten einer beliebigen Anzahl anderer Entitäten zugeordnet ist.

Wenn Sie erst seit kurzem mit EF arbeiten, ist das Ausprobieren der Beispiele, die oben in den Aufzählungszeichen verknüpft sind, eine gute Möglichkeit ein Gefühl für die Funktionsweise von Beziehungen zu erhalten.

Weitere Informationen zu den Eigenschaften von Entitätstypen, die an der Beziehungszuordnung beteiligt sind, finden Sie unter:

EF-Modelle werden mit einer Kombination aus drei Mechanismen erstellt: Konventionen, Zuordnungsattribute und die Modell-Generator-API. Die meisten Beispiele zeigen die Modellerstellungs-API. Weitere Informationen zu anderen Optionen finden Sie unter:

  • Beziehungskonventionen, die Entitätstypen, deren Eigenschaften und die Beziehungen zwischen den Typen ermitteln.
  • Beziehungszuordnungsattribute, die für einige Aspekte der Beziehungskonfiguration als eine Alternative zur Modellerstellungs-API verwendet werden können.

Wichtig

Die Modellerstellungs-API ist die endgültige Wahrheitsquelle für das EF-Modell. Sie hat immer Vorrang vor der Konfiguration, die durch Konvention ermittelt oder durch Zuordnungsattribute angegeben wurde. Sie ist auch der einzige Mechanismus mit voller Genauigkeit, mit dem jeder Aspekt des EF-Modell konfiguriert werden kann.

Weitere Themen im Zusammenhang mit Beziehungen sind:

  • Löschweitergaben, durch die beschrieben wird, wie verwandte Entitäten automatisch gelöscht werden können, wenn SaveChanges oder SaveChangesAsync aufgerufen wird.
  • Im Besitz befindliche Entitätstypen verwenden eine spezielle Art von "Owning"-Beziehung, die eine stärkere Verbindung zwischen den beiden Typen als die beschriebene "normale" Beziehung impliziert. Viele der hier beschriebenen Konzepte für normale Beziehungen werden auf im Besitz befindliche Beziehungen übertragen. Eigene Beziehungen haben jedoch auch eigene spezielle Verhaltensweisen.

Tipp

Lesen Sie in der Dokumentation nach Bedarf das Glossar der Beziehungsbegriffe, um die verwendete Terminologie zu verstehen.

Verwenden von Beziehungen

Beziehungen, die im Modell definiert sind, können auf verschiedene Arten verwendet werden. Beispiel: