Fließende API-BeziehungenFluent API - Relationships

Hinweis

Diese Seite enthält Informationen zum Einrichten von Beziehungen in Ihrem Code First-Modell mithilfe der fließend-API.This page provides information about setting up relationships in your Code First model using the fluent API. Allgemeine Informationen zu Beziehungen in EF und zum Zugreifen auf und Bearbeiten von Daten mithilfe von Beziehungen finden Sie unter Beziehungen & Navigations Eigenschaften.For general information about relationships in EF and how to access and manipulate data using relationships, see Relationships & Navigation Properties.

Beim Arbeiten mit Code First definieren Sie das Modell, indem Sie Ihre Domänen-CLR-Klassen definieren.When working with Code First, you define your model by defining your domain CLR classes. Standardmäßig verwendet Entity Framework die Code First Konventionen, um die Klassen dem Datenbankschema zuzuordnen.By default, Entity Framework uses the Code First conventions to map your classes to the database schema. Wenn Sie die Benennungs Konventionen für Code First verwenden, können Sie sich in den meisten Fällen auf Code First verlassen, um Beziehungen zwischen den Tabellen basierend auf den Fremdschlüsseln und Navigations Eigenschaften einzurichten, die Sie für die Klassen definieren.If you use the Code First naming conventions, in most cases you can rely on Code First to set up relationships between your tables based on the foreign keys and navigation properties that you define on the classes. Wenn Sie den Konventionen beim Definieren der Klassen nicht folgen, oder wenn Sie die Funktionsweise der Konventionen ändern möchten, können Sie die-Klasse mit der flüssigen API oder Daten Anmerkungen so konfigurieren, dass Code First die Beziehungen zwischen den Tabellen zuordnen kann.If you do not follow the conventions when defining your classes, or if you want to change the way the conventions work, you can use the fluent API or data annotations to configure your classes so Code First can map the relationships between your tables.

EinführungIntroduction

Beim Konfigurieren einer Beziehung mit der flüssigen API beginnen Sie mit der entitytypeconfiguration-Instanz und verwenden dann die hasrequired-, hasoptional-oder hasMany-Methode, um den Beziehungstyp anzugeben, an dem diese Entität beteiligt ist.When configuring a relationship with the fluent API, you start with the EntityTypeConfiguration instance and then use the HasRequired, HasOptional, or HasMany method to specify the type of relationship this entity participates in. Die hasrequired-Methode und die hasoptional-Methode akzeptieren einen Lambda-Ausdruck, der eine Verweis Navigations Eigenschaft darstellt.The HasRequired and HasOptional methods take a lambda expression that represents a reference navigation property. Die hasMany-Methode nimmt einen Lambda-Ausdruck an, der eine Auflistungs Navigations Eigenschaft darstellt.The HasMany method takes a lambda expression that represents a collection navigation property. Anschließend können Sie mithilfe der Methoden withrequired, withoptional und withmany eine umgekehrte Navigations Eigenschaft konfigurieren.You can then configure an inverse navigation property by using the WithRequired, WithOptional, and WithMany methods. Diese Methoden verfügen über über Ladungen, die keine Argumente annehmen und zum Angeben der Kardinalität mit unidirektionaler Navigation verwendet werden können.These methods have overloads that do not take arguments and can be used to specify cardinality with unidirectional navigations.

Anschließend können Sie die Fremdschlüssel Eigenschaften mithilfe der hasforeign nkey-Methode konfigurieren.You can then configure foreign key properties by using the HasForeignKey method. Diese Methode verwendet einen Lambda-Ausdruck, der die Eigenschaft darstellt, die als Fremdschlüssel verwendet werden soll.This method takes a lambda expression that represents the property to be used as the foreign key.

Konfigurieren einer erforderlichen und optionalen Beziehung (One-to – Zero-or-one)Configuring a Required-to-Optional Relationship (One-to–Zero-or-One)

Im folgenden Beispiel wird eine 1:0-oder 1-Beziehung konfiguriert.The following example configures a one-to-zero-or-one relationship. Officezuweisung verfügt über die InstructorID-Eigenschaft, bei der es sich um einen Primärschlüssel und einen Fremdschlüssel handelt, da der Name der Eigenschaft nicht der Konvention folgt, die die Haskey-Methode verwendet, um den Primärschlüssel zu konfigurieren.The OfficeAssignment has the InstructorID property that is a primary key and a foreign key, because the name of the property does not follow the convention the HasKey method is used to configure the primary key.

// Configure the primary key for the OfficeAssignment
modelBuilder.Entity<OfficeAssignment>()
    .HasKey(t => t.InstructorID);

// Map one-to-zero or one relationship
modelBuilder.Entity<OfficeAssignment>()
    .HasRequired(t => t.Instructor)
    .WithOptional(t => t.OfficeAssignment);

Konfigurieren einer Beziehung, bei der beide Enden (eins zu eins) erforderlich sindConfiguring a Relationship Where Both Ends Are Required (One-to-One)

In den meisten Fällen können Entity Framework ableiten, welcher Typ der abhängige Typ ist und welcher der Prinzipal in einer Beziehung ist.In most cases Entity Framework can infer which type is the dependent and which is the principal in a relationship. Wenn jedoch beide Enden der Beziehung erforderlich sind oder beide Seiten optional sind Entity Framework den abhängigen und den Prinzipal nicht identifizieren können.However, when both ends of the relationship are required or both sides are optional Entity Framework cannot identify the dependent and principal. Wenn beide Enden der Beziehung erforderlich sind, verwenden Sie withrequirements dprincipal oder withrequirements ddependent nach der hasrequired-Methode.When both ends of the relationship are required, use WithRequiredPrincipal or WithRequiredDependent after the HasRequired method. Wenn beide Enden der Beziehung optional sind, verwenden Sie withoptionalprincipal oder withoptionaldependent nach der hasoptionalen-Methode.When both ends of the relationship are optional, use WithOptionalPrincipal or WithOptionalDependent after the HasOptional method.

// Configure the primary key for the OfficeAssignment
modelBuilder.Entity<OfficeAssignment>()
    .HasKey(t => t.InstructorID);

modelBuilder.Entity<Instructor>()
    .HasRequired(t => t.OfficeAssignment)
    .WithRequiredPrincipal(t => t.Instructor);

Konfigurieren einer m:n-BeziehungConfiguring a Many-to-Many Relationship

Der folgende Code konfiguriert eine m:n-Beziehung zwischen den Kurs-und Dozenten Typen.The following code configures a many-to-many relationship between the Course and Instructor types. Im folgenden Beispiel werden die standardmäßigen Code First Konventionen verwendet, um eine jointabelle zu erstellen.In the following example, the default Code First conventions are used to create a join table. Daher wird die Tabelle CourseInstructor mit Course_CourseID-und Instructor_InstructorID-Spalten erstellt.As a result the CourseInstructor table is created with Course_CourseID and Instructor_InstructorID columns.

modelBuilder.Entity<Course>()
    .HasMany(t => t.Instructors)
    .WithMany(t => t.Courses)

Wenn Sie den Namen der jointabelle und die Namen der Spalten in der Tabelle angeben möchten, müssen Sie mit der Map-Methode eine zusätzliche Konfiguration durchführen.If you want to specify the join table name and the names of the columns in the table you need to do additional configuration by using the Map method. Der folgende Code generiert die CourseInstructor-Tabelle mit den Spalten CourseID und InstructorID.The following code generates the CourseInstructor table with CourseID and InstructorID columns.

modelBuilder.Entity<Course>()
    .HasMany(t => t.Instructors)
    .WithMany(t => t.Courses)
    .Map(m =>
    {
        m.ToTable("CourseInstructor");
        m.MapLeftKey("CourseID");
        m.MapRightKey("InstructorID");
    });

Konfigurieren einer Beziehung mit einer Navigations EigenschaftConfiguring a Relationship with One Navigation Property

Eine eindirektionale (auch als unidirektional bezeichnete Beziehung bezeichnet) ist, wenn eine Navigations Eigenschaft nur für eine der Enden der Beziehung definiert wird, nicht für beides.A one-directional (also called unidirectional) relationship is when a navigation property is defined on only one of the relationship ends and not on both. Gemäß der Konvention interpretiert Code First immer eine unidirektionale Beziehung als 1: n-Beziehung.By convention, Code First always interprets a unidirectional relationship as one-to-many. Wenn Sie z. b. eine eins-zu-eins-Beziehung zwischen "Instructor" und "officezuweisung" wünschen, bei der nur eine Navigations Eigenschaft für den Typ "Instructor" vorhanden ist, müssen Sie die fließende API verwenden, um diese Beziehung zu konfigurieren.For example, if you want a one-to-one relationship between Instructor and OfficeAssignment, where you have a navigation property on only the Instructor type, you need to use the fluent API to configure this relationship.

// Configure the primary Key for the OfficeAssignment
modelBuilder.Entity<OfficeAssignment>()
    .HasKey(t => t.InstructorID);

modelBuilder.Entity<Instructor>()
    .HasRequired(t => t.OfficeAssignment)
    .WithRequiredPrincipal();

Aktivieren von Cascade DeleteEnabling Cascade Delete

Mithilfe der Methode "willcascadeondelete" können Sie die Lösch Weitergabe für eine Beziehung konfigurieren.You can configure cascade delete on a relationship by using the WillCascadeOnDelete method. Wenn ein Fremdschlüssel für die abhängige Entität keine NULL-Werte zulässt, legt Code First den Löschvorgang für die Beziehung fest.If a foreign key on the dependent entity is not nullable, then Code First sets cascade delete on the relationship. Wenn ein Fremdschlüssel für die abhängige Entität NULL-Werte zulässt, legt Code First für die Beziehung keine Lösch Weitergabe fest, und wenn der Prinzipal gelöscht wird, wird der Fremdschlüssel auf NULL festgelegt.If a foreign key on the dependent entity is nullable, Code First does not set cascade delete on the relationship, and when the principal is deleted the foreign key will be set to null.

Sie können diese kaskadierenden Lösch Konventionen mithilfe von entfernen:You can remove these cascade delete conventions by using:

Modelbuilder. Conventions. Remove <OneToManyCascadeDeleteConvention> ()modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
Modelbuilder. Conventions. Remove <ManyToManyCascadeDeleteConvention> ()modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()

Der folgende Code konfiguriert die Beziehung als erforderlich und deaktiviert die Lösch Weitergabe.The following code configures the relationship to be required and then disables cascade delete.

modelBuilder.Entity<Course>()
    .HasRequired(t => t.Department)
    .WithMany(t => t.Courses)
    .HasForeignKey(d => d.DepartmentID)
    .WillCascadeOnDelete(false);

Konfigurieren eines zusammengesetzten fremd SchlüsselsConfiguring a Composite Foreign Key

Wenn der Primärschlüssel des Abteilungs Typs aus "DepartmentID" und "Name Properties" besteht, würden Sie den Primärschlüssel für die Abteilung und den Fremdschlüssel für die Kurs Typen wie folgt konfigurieren:If the primary key on the Department type consisted of DepartmentID and Name properties, you would configure the primary key for the Department and the foreign key on the Course types as follows:

// Composite primary key
modelBuilder.Entity<Department>()
.HasKey(d => new { d.DepartmentID, d.Name });

// Composite foreign key
modelBuilder.Entity<Course>()  
    .HasRequired(c => c.Department)  
    .WithMany(d => d.Courses)
    .HasForeignKey(d => new { d.DepartmentID, d.DepartmentName });

Umbenennen eines fremd Schlüssels, der nicht im Modell definiert istRenaming a Foreign Key That Is Not Defined in the Model

Wenn Sie keinen Fremdschlüssel für den CLR-Typ definieren, aber angeben möchten, welcher Name in der Datenbank enthalten sein soll, gehen Sie wie folgt vor:If you choose not to define a foreign key on the CLR type, but want to specify what name it should have in the database, do the following:

modelBuilder.Entity<Course>()
    .HasRequired(c => c.Department)
    .WithMany(t => t.Courses)
    .Map(m => m.MapKey("ChangedDepartmentID"));

Konfigurieren eines Fremdschlüssel namens, der nicht der Code First Konvention folgtConfiguring a Foreign Key Name That Does Not Follow the Code First Convention

Wenn die Foreign Key-Eigenschaft in der Course-Klasse anstelle von DepartmentID "somedepartmentid" genannt wurde, müssen Sie Folgendes durchführen, um anzugeben, dass "somementid" der Fremdschlüssel sein soll:If the foreign key property on the Course class was called SomeDepartmentID instead of DepartmentID, you would need to do the following to specify that you want SomeDepartmentID to be the foreign key:

modelBuilder.Entity<Course>()
         .HasRequired(c => c.Department)
         .WithMany(d => d.Courses)
         .HasForeignKey(c => c.SomeDepartmentID);

In Beispielen verwendetes ModellModel Used in Samples

Das folgende Code First Modell wird für die Beispiele auf dieser Seite verwendet.The following Code First model is used for the samples on this page.

using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
// add a reference to System.ComponentModel.DataAnnotations DLL
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using System;

public class SchoolEntities : DbContext
{
    public DbSet<Course> Courses { get; set; }
    public DbSet<Department> Departments { get; set; }
    public DbSet<Instructor> Instructors { get; set; }
    public DbSet<OfficeAssignment> OfficeAssignments { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Configure Code First to ignore PluralizingTableName convention
        // If you keep this convention then the generated tables will have pluralized names.
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

public class Department
{
    public Department()
    {
        this.Courses = new HashSet<Course>();
    }
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }
    public decimal Budget { get; set; }
    public System.DateTime StartDate { get; set; }
    public int? Administrator { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; private set; }
}

public class Course
{
    public Course()
    {
        this.Instructors = new HashSet<Instructor>();
    }
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
    public virtual ICollection<Instructor> Instructors { get; private set; }
}

public partial class OnlineCourse : Course
{
    public string URL { get; set; }
}

public partial class OnsiteCourse : Course
{
    public OnsiteCourse()
    {
        Details = new Details();
    }

    public Details Details { get; set; }
}

public class Details
{
    public System.DateTime Time { get; set; }
    public string Location { get; set; }
    public string Days { get; set; }
}

public class Instructor
{
    public Instructor()
    {
        this.Courses = new List<Course>();
    }

    // Primary key
    public int InstructorID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public System.DateTime HireDate { get; set; }

    // Navigation properties
    public virtual ICollection<Course> Courses { get; private set; }
}

public class OfficeAssignment
{
    // Specifying InstructorID as a primary
    [Key()]
    public Int32 InstructorID { get; set; }

    public string Location { get; set; }

    // When Entity Framework sees Timestamp attribute
    // it configures ConcurrencyCheck and DatabaseGeneratedPattern=Computed.
    [Timestamp]
    public Byte[] Timestamp { get; set; }

    // Navigation property
    public virtual Instructor Instructor { get; set; }
}