Teilen über


1:n-Beziehungen

1:N-Beziehungen werden verwendet, wenn eine einzelne Entität einer beliebigen Anzahl anderer Entitäten zugeordnet ist. Beispielsweise kann ein Blog viele zugeordnete Posts aufweisen, aber jeder Post ist nur einem Blog zugeordnet.

Dieses Dokument umfasst viele Beispiele. Die Beispiele beginnen mit allgemeinen Fällen, die auch Konzepte einführen. In späteren Beispielen werden weniger häufige Arten der Konfiguration behandelt. Eine gute Herangehensweise ist es, die ersten paar Beispiele und Konzepte zu verstehen und sich dann je nach Ihren speziellen Bedürfnissen den späteren Beispielen zuzuwenden. Auf der Grundlage dieses Ansatzes beginnen wir mit einfachen „erforderlichen“ und „optionalen“ 1:N-Beziehungen.

Tipp

Den Code für alle folgenden Beispiele finden Sie in OneToMany.cs.

Erforderliche 1:N-Beziehung

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

Eine 1:N-Beziehung besteht aus:

  • Mindestens einer Primär- oder Alternativschlüsseleigenschaft für die Prinzipalentität. Dies ist das „1“-Ende der Beziehung. Beispiel: Blog.Id.
  • Mindestens eine Fremdschlüsseleigenschaft für die abhängige Entität. Dies ist das „N“-Ende der Beziehung. Beispiel: Post.BlogId.
  • Optional eine Sammlungsnavigation für die Prinzipalentität, die auf die abhängigen Entitäten verweist. Beispiel: Blog.Posts.
  • Optional eine Verweisnavigation für die abhängige Entität, die auf die Prinzipalentität verweist. Beispiel: Post.Blog.

Für die Beziehung in diesem Beispiel gilt daher Folgendes:

  • Die Fremdschlüsseleigenschaft Post.BlogId kann keine Nullwerte zulassen. Dadurch wird die Beziehung „erforderlich“, da jede abhängige (Post) mit einem Prinzipal (Blog) verbunden sein muss, da ihre Fremdschlüsseleigenschaft auf einen Wert festgelegt sein muss.
  • Beide Entitäten weisen Navigationen zur zugehörigen Entität bzw. den zugehörigen Entitäten auf der anderen Seite der Beziehung auf.

Hinweis

Eine erforderliche Beziehung stellt sicher, dass jede abhängige Entität einer bestimmten Prinzipalentität zugeordnet werden muss. Eine Prinzipalentität kann jedoch immer ohne abhängige Entitäten existieren. Das heißt, eine erforderliche Beziehung bedeutet nicht, dass es immer mindestens eine abhängige Entität geben wird. Es gibt keine Möglichkeit im EF-Modell und auch keine Standardmethode in einer relationalen Datenbank, um sicherzustellen, dass ein Prinzipal einer bestimmten Anzahl von abhängigen Entitäten zugeordnet ist. Wenn dies erforderlich ist, muss es in der Anwendungslogik (Geschäftslogik) implementiert werden. Weitere Informationen finden Sie unter Erforderliche Navigationen.

Tipp

Eine Beziehung mit zwei Navigationen – eine von der abhängigen zur Prinzipalentität und eine umgekehrte von der Prinzipalentität zur abhängigen Entität – wird als bidirektionale Beziehung bezeichnet.

Diese Beziehung wird gemäß Konvention erkannt. Dies bedeutet:

  • Blog wird als Prinzipal in der Beziehung ermittelt, während Post als abhängige Entität erkannt wird.
  • Post.BlogId wird als Fremdschlüssel der abhängigen Entität erkannt, der auf den Primärschlüssel Blog.Id des Prinzipals verweist. Die Beziehung wird als erforderlich erkannt, da Post.BlogId keine Nullwerte zulässt.
  • Blog.Posts wird als Sammlungsnavigation erkannt.
  • Post.Blog wird als Verweisnavigation erkannt.

Wichtig

Wenn Sie Nullwerte zulassende C#-Verweistypen verwenden, muss die Verweisnavigation Nullwerte zulassen, wenn die Fremdschlüsseleigenschaft Nullwerte zulässt. Wenn die Fremdschlüsseleigenschaft „Non-Nullable“ ist, dann kann die Verweisnavigation entsprechend Nullwerte zulassen oder nicht. In diesem Fall ist Post.BlogId „Non-Nullable“, und Post.Blog ist auch „Non-Nullable“. Das = null!;-Konstrukt wird verwendet, um dies für den C#-Compiler als Absicht zu kennzeichnen, da EF normalerweise die Blog-Instanz festlegt und diese bei einer vollständig geladenen Beziehung nicht NULL sein kann. Weitere Informationen finden Sie unter Arbeiten mit Nullable-Verweistypen.

In Fällen, in denen die Navigationen, Fremdschlüssel oder die erforderliche/optionale Art der Beziehung nicht gemäß der Konvention ermittelt werden, können diese Elemente explizit konfiguriert werden. Beispiel:

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

Im obigen Beispiel beginnt die Konfiguration der Beziehungen mit HasMany für den Prinzipalentitätstyp (Blog) und darauf folgt WithOne. Wie bei allen Beziehungen ist es genau gleichbedeutend, stattdessen mit dem abhängigen Entitätstyp (Post) zu beginnen und HasOne gefolgt von WithMany zu verwenden. Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>()
        .HasOne(e => e.Blog)
        .WithMany(e => e.Posts)
        .HasForeignKey(e => e.BlogId)
        .IsRequired();
}

Keine dieser Optionen ist besser als die andere, da beide zu genau der gleichen Konfiguration führen.

Tipp

Es ist nie erforderlich, eine Beziehung zweimal zu konfigurieren, einmal vom Prinzipal aus und dann noch einmal von der abhängigen Entität aus. Auch der Versuch, die Prinzipal- und die abhängige Hälfte einer Beziehung getrennt zu konfigurieren, funktioniert in der Regel nicht. Sie können jede Beziehung entweder von der einen oder von der anderen Seite aus konfigurieren und dann den Konfigurationscode nur einmal schreiben.

Optionale 1:N-Beziehung

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public int? BlogId { get; set; } // Optional foreign key property
    public Blog? Blog { get; set; } // Optional reference navigation to principal
}

Dies ist dasselbe wie im vorherigen Beispiel, außer dass die Fremdschlüsseleigenschaft und die Navigation zum Prinzipal jetzt Nullwerte zulassen. Dadurch wird die Beziehung „optional“, denn eine abhängige Entität (Post) kann existieren, ohne einem Prinzipal (Blog) zugeordnet zu sein.

Wichtig

Wenn Sie Nullwerte zulassende C#-Verweistypen verwenden, muss die Verweisnavigation Nullwerte zulassen, wenn die Fremdschlüsseleigenschaft Nullwerte zulässt. In diesem Fall lässt Post.BlogId Nullwerte zu, daher muss Post.Blog ebenfalls Nullwerte zulassen. Weitere Informationen finden Sie unter Arbeiten mit Nullable-Verweistypen.

Wie zuvor wird diese Beziehung gemäß Konvention erkannt. In Fällen, in denen die Navigationen, Fremdschlüssel oder die erforderliche/optionale Art der Beziehung nicht gemäß der Konvention ermittelt werden, können diese Elemente explizit konfiguriert werden. Beispiel:

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

Erforderliche 1:N-Beziehung mit Schattenfremdschlüssel

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

In bestimmten Fällen möchten Sie vielleicht keine Fremdschlüsseleigenschaft in Ihrem Modell verwenden, da Fremdschlüssel ein Detail zur Darstellung der Beziehung in der Datenbank sind, das nicht benötigt wird, wenn Sie die Beziehung auf rein objektorientierte Weise verwenden. Wenn Entitäten jedoch serialisiert werden sollen, z. B. um sie über eine Leitung zu versenden, dann können die Fremdschlüsselwerte eine nützliche Möglichkeit sein, die Beziehungsinformationen intakt zu halten, wenn die Entitäten nicht in einer Objektform vorliegen. Es ist daher oft pragmatisch, zu diesem Zweck Fremdschlüsseleigenschaften im .NET-Typ zu behalten. Fremdschlüsseleigenschaften können privat sein, was oft ein guter Kompromiss ist, um zu vermeiden, dass der Fremdschlüssel offengelegt wird, während sein Wert bei der Entität verbleiben kann.

In Anlehnung an die beiden vorherigen Beispiele entfernt dieses Beispiel die Fremdschlüsseleigenschaft aus dem abhängigen Entitätstyp. EF erstellt daher eine Schattenfremdschlüssel-Eigenschaft namens BlogId vom Typ int.

Ein wichtiger Hinweis hier ist, dass Nullwerte zulassende C#-Verweistypen verwendet werden, sodass die NULL-Zulässigkeit der Verweisnavigation verwendet wird, um zu bestimmen, ob die Fremdschlüsseleigenschaft Nullwerte zulässt, und somit, ob die Beziehung optional oder erforderlich ist. Wenn Nullwerte zulassende Referenztypen nicht verwendet werden, dann lässt die Schattenfremdschlüssel-Eigenschaft standardmäßig Nullwerte zu, sodass die Beziehung standardmäßig optional ist. Verwenden Sie in diesem Fall IsRequired, um zu erzwingen, dass die Schattenfremdschlüssel-Eigenschaft „Non-Nullable“ und die Beziehung somit erforderlich ist.

Wie zuvor wird diese Beziehung gemäß Konvention erkannt. In Fällen, in denen die Navigationen, Fremdschlüssel oder die erforderliche/optionale Art der Beziehung nicht gemäß der Konvention ermittelt werden, können diese Elemente explizit konfiguriert werden. Beispiel:

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

Optionale 1:N-Beziehung mit Schattenfremdschlüssel

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public Blog? Blog { get; set; } // Optional reference navigation to principal
}

Wie im vorigen Beispiel wurde die Fremdschlüsseleigenschaft aus dem abhängigen Entitätstyp entfernt. EF erstellt daher eine Schattenfremdschlüssel-Eigenschaft namens BlogId vom Typ int?. Im Gegensatz zum vorherigen Beispiel wird die Fremdschlüsseleigenschaft dieses Mal als „Nullwerte zulassend“ erstellt, da Nullwerte zulassende C#-Verweistypen verwendet werden und die Navigation für den abhängigen Entitätstyp entsprechend Nullwerte zulässt. Dadurch wird die Beziehung optional.

Wenn keine Nullwerte zulassenden C#-Verweistypen verwendet werden, wird die Fremdschlüsseleigenschaft standardmäßig auch als „Nullwerte zulassend“ erstellt. Das bedeutet, dass Beziehungen mit automatisch erstellten Schatteneigenschaften standardmäßig optional sind.

Wie zuvor wird diese Beziehung gemäß Konvention erkannt. In Fällen, in denen die Navigationen, Fremdschlüssel oder die erforderliche/optionale Art der Beziehung nicht gemäß der Konvention ermittelt werden, können diese Elemente explizit konfiguriert werden. Beispiel:

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

1:N-Beziehung ohne Navigation zum Prinzipal

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
}

Für dieses Beispiel wurde die Fremdschlüsseleigenschaft wieder eingeführt, aber die Navigation zu den abhängigen Entitäten wurde entfernt.

Tipp

Eine Beziehung mit nur einer Navigation – eine von der abhängigen Entität zur Prinzipalentität oder eine von der Prinzipalentität zur abhängigen Entität (bzw. zu abhängigen Entitäten), aber nicht beides – wird als unidirektionale Beziehung bezeichnet.

Wie zuvor wird diese Beziehung gemäß Konvention erkannt. In Fällen, in denen die Navigationen, Fremdschlüssel oder die erforderliche/optionale Art der Beziehung nicht gemäß der Konvention ermittelt werden, können diese Elemente explizit konfiguriert werden. Beispiel:

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

Beachten Sie, dass der Aufruf von WithOne keine Argumente aufweist. Dies ist die Möglichkeit, EF mitzuteilen, dass es keine Navigation von Post zu Blog gibt.

Wenn die Konfiguration von der Entität ohne Navigation ausgeht, muss der Typ der Entität am anderen Ende der Beziehung explizit angegeben werden, indem der generische Aufruf HasOne<>() verwendet wird. Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>()
        .HasOne<Blog>()
        .WithMany(e => e.Posts)
        .HasForeignKey(e => e.BlogId)
        .IsRequired();
}

1:N-Beziehung ohne Navigation zum Prinzipal und mit Schattenfremdschlüssel

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
}

In diesem Beispiel werden zwei der vorherigen Beispiele kombiniert, indem sowohl die Fremdschlüsseleigenschaft als auch die Navigation für die abhängige Entität entfernt werden.

Diese Beziehung wird gemäß Konvention als optionale Beziehung erkannt. Da im Code nichts darauf hinweist, dass sie erforderlich sein sollte, ist eine minimale Konfiguration unter Verwendung von IsRequired erforderlich, um eine erforderliche Beziehung zu erstellen. Beispiel:

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

Eine vollständigere Konfiguration kann verwendet werden, um die Navigation und den Fremdschlüsselnamen explizit zu konfigurieren, je nach Bedarf mit einem entsprechenden Aufruf von IsRequired() oder IsRequired(false). Beispiel:

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

1:N-Beziehung ohne Navigation zu abhängigen Entitäten

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

In den beiden vorangegangenen Beispielen gab es Navigationen vom Prinzipal zur abhängigen Entität, aber keine Navigation von der abhängigen Entität zum Prinzipal. Bei den nächsten Beispielen wird die Navigation zur abhängigen Entität wieder eingeführt, während stattdessen die Navigation zum Prinzipal entfernt wird.

Wie zuvor wird diese Beziehung gemäß Konvention erkannt. In Fällen, in denen die Navigationen, Fremdschlüssel oder die erforderliche/optionale Art der Beziehung nicht gemäß der Konvention ermittelt werden, können diese Elemente explizit konfiguriert werden. Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>()
        .HasOne(e => e.Blog)
        .WithMany()
        .HasForeignKey(e => e.BlogId)
        .IsRequired();
}

Beachten Sie erneut, dass WithMany() ohne Argumente aufgerufen wird, um anzuzeigen, dass es keine Navigation in diese Richtung gibt.

Wenn die Konfiguration von der Entität ohne Navigation ausgeht, muss der Typ der Entität am anderen Ende der Beziehung explizit angegeben werden, indem der generische Aufruf HasMany<>() verwendet wird. Beispiel:

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

1:N-Beziehung ohne Navigation

Gelegentlich kann es sinnvoll sein, eine Beziehung ohne Navigationen zu konfigurieren. Eine solche Beziehung kann nur bearbeitet werden, indem der Fremdschlüsselwert direkt geändert wird.

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
}

Diese Beziehung wird nicht gemäß Konvention erkannt, da es keine Hinweise darauf gibt, dass die beiden Typen miteinander verknüpft sind. Sie kann explizit in OnModelCreating konfiguriert werden. Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasMany<Post>()
        .WithOne();
}

Bei dieser Konfiguration wird die Eigenschaft Post.BlogId immer noch gemäß Konvention als Fremdschlüssel erkannt und die Beziehung ist erforderlich, da die Fremdschlüsseleigenschaft keine Nullwerte zulässt. Die Beziehung kann als „optional“ festgelegt werden, indem dafür gesorgt wird, dass die Fremdschlüsseleigenschaft Nullwerte zulässt.

Eine vollständigere explizite Konfiguration dieser Beziehung lautet:

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

1:N-Beziehung mit Alternativschlüssel

In allen bisherigen Beispielen ist die Fremdschlüsseleigenschaft der abhängigen Entität auf die Primärschlüsseleigenschaft des Prinzipals beschränkt. Der Fremdschlüssel kann stattdessen auf eine andere Eigenschaft beschränkt werden, die dann zu einem Alternativschlüssel für den Typ der Prinzipalentität wird. Beispiel:

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public int AlternateId { get; set; } // Alternate key as target of the Post.BlogId foreign key
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

Diese Beziehung wird nicht gemäß Konvention entdeckt, da EF gemäß Konvention immer eine Beziehung zum Primärschlüssel erstellt. Sie kann explizit in OnModelCreating mithilfe eines Aufrufs von HasPrincipalKey konfiguriert werden. Beispiel:

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

HasPrincipalKey kann mit anderen Aufrufen kombiniert werden, um die Navigationen, die Fremdschlüsseleigenschaften und den erforderlichen/optionalen Charakter explizit zu konfigurieren. Beispiel:

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

1:N-Beziehung mit zusammengesetztem Fremdschlüssel

In allen bisherigen Beispielen bestand die Primär- oder Alternativschlüsseleigenschaft des Prinzipals aus einer einzelnen Eigenschaft. Primär- oder Alternativschlüssel können auch aus mehreren Eigenschaften gebildet werden. Sie werden dann als zusammengesetzte Schlüssel bezeichnet. Wenn der Prinzipal einer Beziehung einen zusammengesetzten Schlüssel aufweist, dann muss auch der Fremdschlüssel der abhängigen Entität ein zusammengesetzter Schlüssel mit der gleichen Anzahl von Eigenschaften sein. Beispiel:

// Principal (parent)
public class Blog
{
    public int Id1 { get; set; } // Composite key part 1
    public int Id2 { get; set; } // Composite key part 2
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public int BlogId1 { get; set; } // Required foreign key property part 1
    public int BlogId2 { get; set; } // Required foreign key property part 2
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

Diese Beziehung wird gemäß Konvention erkannt. Der zusammengesetzte Schlüssel selbst muss jedoch explizit konfiguriert werden:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasKey(e => new { e.Id1, e.Id2 });
}

Wichtig

Ein zusammengesetzter Fremdschlüsselwert wird als null betrachtet, wenn einer seiner Eigenschaftswerte NULL ist. Ein zusammengesetzter Fremdschlüssel, bei dem eine Eigenschaft NULL und eine andere nicht NULL ist, wird nicht als Übereinstimmung mit einem Primär- oder Alternativschlüssel mit denselben Werten betrachtet. Beide werden als null betrachtet.

Sowohl HasForeignKey als auch HasPrincipalKey können verwendet werden, um explizit Schlüssel mit mehreren Eigenschaften anzugeben. Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>(
        nestedBuilder =>
        {
            nestedBuilder.HasKey(e => new { e.Id1, e.Id2 });

            nestedBuilder.HasMany(e => e.Posts)
                .WithOne(e => e.Blog)
                .HasPrincipalKey(e => new { e.Id1, e.Id2 })
                .HasForeignKey(e => new { e.BlogId1, e.BlogId2 })
                .IsRequired();
        });
}

Tipp

Im obigen Code wurden die Aufrufe von HasKey und HasMany in einem geschachtelten Generator zusammengefasst. Geschachtelte Generatoren beseitigen die Notwendigkeit, Entity<>() mehrfach für denselben Entitätstyp aufzurufen, sind aber funktional äquivalent zum mehrfachen Aufruf von Entity<>().

Erforderliche 1:N-Beziehung ohne kaskadierendes Delete

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public ICollection<Post> Posts { get; } = new List<Post>(); // Collection navigation containing dependents
}

// Dependent (child)
public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

Gemäß Konvention sind erforderliche Beziehungen für kaskadierendes Delete konfiguriert. Das bedeutet, dass beim Löschen des Prinzipals auch alle von ihm abhängigen Entitäten gelöscht werden, da abhängige Entitäten in der Datenbank nicht ohne einen Prinzipal existieren können. Es ist möglich, EF so zu konfigurieren, dass eine Ausnahme ausgelöst wird, anstatt abhängige Zeilen, die nicht länger existieren können, automatisch zu löschen:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasMany(e => e.Posts)
        .WithOne(e => e.Blog)
        .OnDelete(DeleteBehavior.Restrict);
}

Auf sich selbst verweisende 1:N-Beziehung

In allen vorherigen Beispielen war der Prinzipalentitätstyp ein anderer als der Typ der abhängigen Entität. Das muss nicht der Fall sein. In den folgenden Typen bezieht sich jeder Employee beispielsweise auf andere Employees.

public class Employee
{
    public int Id { get; set; }

    public int? ManagerId { get; set; } // Optional foreign key property
    public Employee? Manager { get; set; } // Optional reference navigation to principal
    public ICollection<Employee> Reports { get; } = new List<Employee>(); // Collection navigation containing dependents
}

Diese Beziehung wird gemäß Konvention erkannt. In Fällen, in denen die Navigationen, Fremdschlüssel oder die erforderliche/optionale Art der Beziehung nicht gemäß der Konvention ermittelt werden, können diese Elemente explizit konfiguriert werden. Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Employee>()
        .HasOne(e => e.Manager)
        .WithMany(e => e.Reports)
        .HasForeignKey(e => e.ManagerId)
        .IsRequired(false);
}