次の方法で共有


一対一リレーションシップ

1 対 1 のリレーションシップは、1 つのエンティティが最大 1 つの他のエンティティに関連付けられている場合に使用されます。 たとえば、 Blog には 1 つの BlogHeaderがあり、その BlogHeader は 1 つの Blogに属します。

このドキュメントは、多くの例を中心に構成されています。 例は、概念も紹介する一般的なケースから始まります。 後の例では、あまり一般的でない種類の構成について説明します。 ここでの適切なアプローチは、最初のいくつかの例と概念を理解し、特定のニーズに基づいて後の例に進むことです。 このアプローチに基づいて、単純な "必須" と "省略可能" の 1 対 1 のリレーションシップから始めます。

ヒント

以下のすべての例のコードは、 OneToOne.csにあります。

必須の 1 対 1

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    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
}

1 対 1 のリレーションシップは、次から構成されます。

  • プリンシパル エンティティの 1 つ以上の 主キープロパティまたは代替キー プロパティ。 たとえば、Blog.Id のようにします。
  • 依存エンティティの 1 つ以上の 外部キー プロパティ。 たとえば、BlogHeader.BlogId のようにします。
  • 必要に応じて、依存エンティティを参照するプリンシパル エンティティの 参照ナビゲーション 。 たとえば、Blog.Header のようにします。
  • 場合によっては、プリンシパルエンティティを参照する依存エンティティの参照ナビゲーション。 たとえば、BlogHeader.Blog のようにします。

ヒント

一対一リレーションシップのどちら側がプリンシパルで、どの側が依存する必要があるのかは、必ずしも明らかではありません。 いくつかの考慮事項は次のとおりです。

  • 2 つの型のデータベース テーブルが既に存在する場合は、外部キー列を持つテーブルを依存型にマップする必要があります。
  • 型は、他の型なしで論理的に存在できない場合、通常は依存型です。 たとえば、存在しないブログのヘッダーを持つことは意味がないため、 BlogHeader は当然依存型です。
  • 自然な親子関係がある場合、通常、子は依存型です。

したがって、この例のリレーションシップの場合は、次のようになります。

  • BlogHeader.BlogId外部キー プロパティは null 許容ではありません。 これにより、すべての依存 (BlogHeader) がBlogがあるため、リレーションシップは "必須" になります。これは、外部キー プロパティを何らかの値に設定する必要があるためです。
  • 両方のエンティティには、リレーションシップの反対側にある関連エンティティを指すナビゲーションがあります。

必要なリレーションシップにより、すべての依存エンティティを一部のプリンシパル エンティティに関連付ける必要があります。 ただし、プリンシパル エンティティは 、依存エンティティなしで常に 存在できます。 つまり、必要なリレーションシップは、依存エンティティが常に存在することを示 すわけではありません 。 プリンシパルが依存データベースに関連付けられていることを確認するために、EF モデルには方法はなく、リレーショナル データベースの標準的な方法もありません。 これが必要な場合は、アプリケーション (ビジネス) ロジックで実装する必要があります。 詳細については、「 必要なナビゲーション 」を参照してください。

ヒント

2 つのナビゲーション (依存からプリンシパルへの 1 つ、プリンシパルから依存への逆) とのリレーションシップは、双方向リレーションシップと呼ばれます。

この関係は 規則によって検出されます。 つまり、

  • Blog はリレーションシップのプリンシパルとして検出され、 BlogHeader は依存として検出されます。
  • BlogHeader.BlogId は、プリンシパルの Blog.Id 主キーを参照する依存の外部キーとして検出されます。 BlogHeader.BlogIdは null 許容ではないため、必要に応じてリレーションシップが検出されます。
  • Blog.BlogHeader は参照ナビゲーションとして検出されます。
  • BlogHeader.Blog は参照ナビゲーションとして検出されます。

Von Bedeutung

C# null 許容参照型を使用する場合、外部キー プロパティが null 許容の場合、依存元からプリンシパルへのナビゲーションは null 許容である必要があります。 外部キー プロパティが null 非許容の場合、ナビゲーションは null 許容であるかもしれませんし、そうでないかもしれません。 この場合、 BlogHeader.BlogId は null 非許容であり、 BlogHeader.Blog も null 非許容です。 構造は、C# コンパイラに対してこれを意図したものであることを示すために使用されます。EF は通常、 インスタンスを設定しますが、完全に読み込まれたリレーションシップではそれを null にすることはできません。 詳細については、「 Null 許容参照型の操作 」を参照してください。

ナビゲーション、外部キー、またはリレーションシップの必須/省略可能な性質が規則によって検出されない場合は、これらの設定を明示的に構成できます。 例えば次が挙げられます。

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

上記の例では、リレーションシップの構成によって、プリンシパル エンティティ型 (Blog) が開始されます。 すべてのリレーションシップと同様に、依存エンティティ型 (BlogHeader) から始めるのとまったく同じです。 例えば次が挙げられます。

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

これらのオプションのどちらも他のオプションよりも優れています。両方ともまったく同じ構成になります。

ヒント

リレーションシップを 2 回構成する必要はありません。1 回はプリンシパルから開始してから、依存元から再度開始します。 また、リレーションシップのプリンシパルと依存する半分を個別に構成しようとしても、通常は機能しません。 どちらか一方の側から各リレーションシップを構成し、構成コードを 1 回だけ記述することを選択します。

オプションの 1 対 1

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

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

これは前の例と同じですが、外部キー プロパティとプリンシパルへのナビゲーションが null 許容になりました。 これにより、依存関係 (BlogHeader) は外部キー プロパティとナビゲーションをに設定することによって、どのプリンシパル (Blog) にも関連付null、リレーションシップは "省略可能" になります。

Von Bedeutung

C# null 許容参照型を使用する場合、外部キー プロパティが null 許容の場合、依存元からプリンシパルへのナビゲーション プロパティは null 許容である必要があります。 この場合、 BlogHeader.BlogId は null 許容であるため、 BlogHeader.Blog も null 許容である必要があります。 詳細については、「 Null 許容参照型の操作 」を参照してください。

以前と同様に、この関係は 規則によって検出されます。 ナビゲーション、外部キー、またはリレーションシップの必須/省略可能な性質が規則によって検出されない場合は、これらの設定を明示的に構成できます。 例えば次が挙げられます。

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

主キーと主キー間の必須の1対1リレーションシップ

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

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

一対多リレーションシップとは異なり、1 対 1 のリレーションシップの依存側では、主キー プロパティまたはプロパティを外部キー プロパティとして使用できます。 これは PK-to-PK リレーションシップと呼ばれることがよくあります。 これは、プリンシパル型と依存型が同じ主キー型を持ち、結果のリレーションシップが常に必要な場合にのみ可能です。これは、依存の主キーを null 許容にできないためです。

規則によって外部キーが検出されない 1 対 1 のリレーションシップは、リレーションシップのプリンシパルと依存する末尾を示すように構成する必要があります。 これは通常、 HasForeignKeyの呼び出しで行われます。 例えば次が挙げられます。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>();
}

ヒント

HasPrincipalKey この目的にも使用できますが、あまり一般的ではありません。

HasForeignKeyの呼び出しでプロパティが指定されておらず、主キーが適切な場合は、外部キーとして使用されます。 ナビゲーション、外部キー、またはリレーションシップの必須/省略可能な性質が規則によって検出されない場合は、これらの設定を明示的に構成できます。 例えば次が挙げられます。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>(e => e.Id)
        .IsRequired();
}

シャドウ外部キーが必要な1対1の関係

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

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

場合によっては、外部キーはデータベースでのリレーションシップの表現方法の詳細であるため、モデルに外部キー プロパティが必要ない場合があります。これは、純粋にオブジェクト指向の方法でリレーションシップを使用する場合には必要ありません。 ただし、エンティティをシリアル化する場合 (たとえば、ワイヤ経由で送信する場合など)、エンティティがオブジェクトフォームにない場合にリレーションシップ情報をそのまま保持する場合は、外部キー値が役立つ場合があります。 そのため、多くの場合、この目的のために外部キー プロパティを .NET 型に保持することは実用的です。 外部キーのプロパティはプライベートにすることができます。これは、多くの場合、外部キーを公開せずに、その値をエンティティと共に移動できるようにするための良い妥協案です。

前の例に続いて、この例では依存エンティティ型から外部キー プロパティを削除します。 ただし、主キーを使用する代わりに、EF は型のBlogIdと呼ばれるintを作成するように指示されます。

ここで注意すべき重要な点は、 C# の null 許容参照型 が使用されているため、依存からプリンシパルへのナビゲーションの null 許容は、外部キー プロパティが null 許容かどうか、およびリレーションシップが省略可能か必須かを判断するために使用されます。 null 許容参照型が使用されていない場合、シャドウ外部キー プロパティは既定で null 許容になり、リレーションシップは既定で省略可能になります。 この場合は、 IsRequired を使用して、シャドウ外部キー プロパティを null 非許容にし、リレーションシップを必須にします。

この関係では、主要な側と従属する側を示す設定が再度必要です。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>("BlogId");
}

ナビゲーション、外部キー、またはリレーションシップの必須/省略可能な性質が規則によって検出されない場合は、これらの設定を明示的に構成できます。 例えば次が挙げられます。

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

シャドウ外部キーを使用したオプションの 1 対 1

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

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

前の例と同様に、外部キー プロパティは依存エンティティ型から削除されています。 ただし、前の例とは異なり、今回は、 C# の null 許容参照型 が使用されており、依存エンティティ型のナビゲーションが null 許容であるため、外部キー プロパティが null 許容として作成されます。 これにより、リレーションシップは省略可能になります。

C# null 許容参照型が使用されていない場合、外部キー プロパティは既定で null 許容として作成されます。 つまり、自動的に作成されるシャドウ プロパティを持つリレーションシップは、既定では省略可能です。

前と同様に、このリレーションシップには、プリンシパルと依存の終了を示す構成が必要です。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>("BlogId");
}

ナビゲーション、外部キー、またはリレーションシップの必須/省略可能な性質が規則によって検出されない場合は、これらの設定を明示的に構成できます。 例えば次が挙げられます。

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

プリンシパルへのナビゲーションなしの 1 対 1

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

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

この例では、外部キー プロパティが再導入されましたが、依存先のナビゲーションは削除されています。

ヒント

依存からプリンシパルへのナビゲーション1つ、またはプリンシパルから依存へのナビゲーション1つのみを含むリレーションシップは、一方向リレーションシップと呼ばれます。

このリレーションシップは規則 によって検出されます。外部キーが検出されるため、依存側を示します。 ナビゲーション、外部キー、またはリレーションシップの必須/省略可能な性質が規則によって検出されない場合は、これらの設定を明示的に構成できます。 例えば次が挙げられます。

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

WithOneの呼び出しには引数がないことに注意してください。 これは、 BlogHeader から Blogへのナビゲーションがないことを EF に通知する方法です。

ナビゲーションのないエンティティから構成を開始する場合は、一般的な HasOne<>() 呼び出しを使用して、リレーションシップのもう一方の端にあるエンティティの型を明示的に指定する必要があります。 例えば次が挙げられます。

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

プリンシパルへのナビゲーションがなく、シャドウ外部キーを用いる 1 対 1

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

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

この例では、外部キー プロパティと依存オブジェクトのナビゲーションの両方を削除して、前の例の 2 つを組み合わせます。

前と同様に、このリレーションシップには、プリンシパルと依存の終了を示す構成が必要です。

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

より完全な構成を使用して、必要に応じて IsRequired() または IsRequired(false) を適切に呼び出して、ナビゲーションと外部キー名を明示的に構成できます。 例えば次が挙げられます。

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

依存対象へのナビゲーションなしの1対1

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

// Dependent (child)
public class BlogHeader
{
    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
}

前の 2 つの例には、プリンシパルから依存元へのナビゲーションがありましたが、依存元からプリンシパルへのナビゲーションはありませんでした。 次のいくつかの例では、依存オブジェクトのナビゲーションが再導入され、プリンシパルのナビゲーションは削除されます。

慣例により、EF はこれを一対多リレーションシップとして扱います。 1 対 1 にするには、最小限の構成が必要です。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<BlogHeader>()
        .HasOne(e => e.Blog)
        .WithOne();
}

この方向にナビゲーションがないことを示す引数なしで WithOne() が呼び出されていることに注意してください。

ナビゲーション、外部キー、またはリレーションシップの必須/省略可能な性質が規則によって検出されない場合は、これらの設定を明示的に構成できます。 例えば次が挙げられます。

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

ナビゲーションのないエンティティから構成を開始する場合は、一般的な HasOne<>() 呼び出しを使用して、リレーションシップのもう一方の端にあるエンティティの型を明示的に指定する必要があります。 例えば次が挙げられます。

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

ナビゲーションのない 1 対 1

場合によっては、ナビゲーションのないリレーションシップを構成すると便利な場合があります。 このようなリレーションシップは、外部キー値を直接変更することによってのみ操作できます。

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

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

このリレーションシップは、2 つの型が関連していることを示すナビゲーションがないため、規則によって検出されません。 OnModelCreatingで明示的に構成できます。 例えば次が挙げられます。

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

この構成では、 BlogHeader.BlogId プロパティは規則によって外部キーとして引き続き検出され、外部キー プロパティは null 許容ではないため、リレーションシップは "必須" です。 リレーションシップは、外部キー プロパティを null 値にすることで "省略可能" にすることができます。

このリレーションシップのより完全な明示的な構成は次のとおりです。

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

代替キーを使用した 1 対 1

ここまでのすべての例では、依存元の外部キー プロパティはプリンシパルの主キー プロパティに制限されています。 代わりに、外部キーを別のプロパティに制限できます。これにより、プリンシパル エンティティ型の代替キーになります。 例えば次が挙げられます。

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public int AlternateId { get; set; } // Alternate key as target of the BlogHeader.BlogId foreign key
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    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
}

EF は常に規則によって主キーとのリレーションシップを作成するため、このリレーションシップは規則によって検出されません。 OnModelCreatingHasPrincipalKeyの呼び出しを利用して明示的に構成することができます。 例えば次が挙げられます。

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

HasPrincipalKey を他の呼び出しと組み合わせて、ナビゲーション、外部キープロパティ、必須/オプションの性質を明示的に構成できます。 例えば次が挙げられます。

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

複合外部キーを使用した 1 対 1

ここまでのすべての例では、プリンシパルの主キー プロパティまたは代替キー プロパティが 1 つのプロパティで構成されていました。 主キーまたは代替キーは、複数のプロパティを形成することもできます。これらは "複合キー" と呼ばれます。 リレーションシップのプリンシパルに複合キーがある場合、依存する外部キーも同じ数のプロパティを持つ複合キーである必要があります。 例えば次が挙げられます。

// Principal (parent)
public class Blog
{
    public int Id1 { get; set; } // Composite key part 1
    public int Id2 { get; set; } // Composite key part 2
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    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
}

この関係は規則によって検出されます。 ただし、複合キーは自動的に検出されないため、複合キーが明示的に構成されている場合にのみ検出されます。 例えば次が挙げられます。

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

Von Bedeutung

複合外部キー値は、そのプロパティ値のいずれかが null の場合に null と見なされます。 1 つのプロパティ null と別の null 以外の複合外部キーは、同じ値を持つ主キーまたは代替キーとの一致とは見なされません。 どちらも nullと見なされます。

HasForeignKeyHasPrincipalKeyの両方を使用して、複数のプロパティを持つキーを明示的に指定できます。 例えば次が挙げられます。

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

            nestedBuilder.HasOne(e => e.Header)
                .WithOne(e => e.Blog)
                .HasPrincipalKey<Blog>(e => new { e.Id1, e.Id2 })
                .HasForeignKey<BlogHeader>(e => new { e.BlogId1, e.BlogId2 })
                .IsRequired();
        });
}

ヒント

上記のコードでは、 HasKeyHasOne の呼び出しは、入れ子になったビルダーにグループ化されています。 入れ子になったビルダーは、同じエンティティ型 Entity<>() 複数回呼び出す必要はありませんが、機能的には Entity<>() 複数回呼び出すことと同等です。

連鎖削除を伴わない必須の 1 対 1 条件

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    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
}

規則により、必要なリレーションシップは 連鎖削除するように構成されます。 これは、プリンシパルが削除された後に、依存オブジェクトがデータベースに存在できないためです。 データベースは、存在しなくなった依存行を自動的に削除するのではなく、通常はアプリケーションをクラッシュさせるエラーを生成するように構成できます。 これには、いくつかの構成が必要です。

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

1 対 1 の自己参照

上記のすべての例では、プリンシパル エンティティ型は依存エンティティ型とは異なっていました。 そうである必要はありません。 たとえば、次の型では、各 Person は必要に応じて別の Personに関連付けられます。

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

    public int? HusbandId { get; set; } // Optional foreign key property
    public Person? Husband { get; set; } // Optional reference navigation to principal
    public Person? Wife { get; set; } // Reference navigation to dependent
}

この関係は 規則によって検出されます。 ナビゲーション、外部キー、またはリレーションシップの必須/省略可能な性質が規則によって検出されない場合は、これらの設定を明示的に構成できます。 例えば次が挙げられます。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .HasOne(e => e.Husband)
        .WithOne(e => e.Wife)
        .HasForeignKey<Person>(e => e.HusbandId)
        .IsRequired(false);
}

1 対 1 の自己参照リレーションシップの場合、プリンシパルエンティティ型と依存エンティティ型は同じであるため、外部キーを含む型を指定しても、依存側は明確になりません。 この場合、HasOneで指定されたナビゲーションは依存関係からプリンシパルへの方向を示し、WithOneで指定されたナビゲーションはプリンシパルから依存関係への方向を示します。