リレーションシップの概要
このドキュメントでは、オブジェクト モデルとリレーショナル データベースのリレーションシップの表現の簡単な概要について説明します。この 2 つの間で EF Core がどのようにマップされるかを含みます。
オブジェクト モデルのリレーションシップ
リレーションシップは、2 つのエンティティが互いを関連付ける方法を定義します。 たとえば、ブログの投稿をモデル化する場合、各投稿は公開されているブログに関連し、ブログはそのブログに公開されているすべての投稿に関連します。
C# のようなオブジェクト指向言語では、ブログと投稿は通常、 と Post
の 2 つのクラスBlog
で表されます。 次に例を示します。
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; }
}
上記のクラスでは、 と Post
が関連していることを示すものBlog
はありません。 これは、発行先の への参照Post
Blog
を追加することで、オブジェクト モデルに追加できます。
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; }
}
同様に、同じリレーションシップの反対方向は、 の各 Blog
オブジェクトのPost
コレクションとして表すことができます。
public class Blog
{
public string Name { get; set; }
public virtual Uri SiteUri { get; set; }
public ICollection<Post> Posts { get; }
}
この接続はBlog
Post
、逆にPost
Blog
、EF Core では "リレーションシップ" と呼ばれます。
重要
通常、 1 つの リレーションシップはどちらの方向でも走査できます。 この例では、 プロパティBlog
を使用して から、 Post
プロパティPost
をBlog.Posts
使用して Post.Blog
に戻りますBlog
。 これは 1 つの リレーションシップであり、2 つではありません。
ヒント
EF Core では、 Blog.Posts
プロパティと Post.Blog
プロパティは "ナビゲーション" と呼ばれます。
リレーショナル データベースのリレーションシップ
リレーショナル データベースは、外部キーを使用するリレーションシップを表します。 たとえば、SQL ServerまたはAzure SQLを使用すると、次の表を使用して クラスPost
と Blog
クラスを表すことができます。
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]));
このリレーショナル モデルでは、 Posts
テーブルと Blogs
テーブルには、それぞれ "主キー" 列が指定されます。 主キーの値は、各投稿またはブログを一意に識別します。 さらに、テーブルには Blogs
"外部キー" 列が指定されます。 Blogs
主キー列Id
は、テーブルのBlogId
外部キー列Posts
によって参照されます。 この列は、 の列の値が の列Posts
のBlogId
値Id
Blogs
と一致するように "制約付き" です。 この一致により、すべての投稿が関連するブログが決まります。 たとえば、テーブルの BlogId
1 行の Posts
値が 7 の場合、その行によって表される投稿は、主キー 7 を使用してブログで公開されます。
EF Core でのリレーションシップのマッピング
EF Core リレーションシップ マッピングは、リレーショナル データベースで使用される主キー/外部キー表現を、オブジェクト モデルで使用されるオブジェクト間の参照にマッピングすることです。
最も基本的な意味では、これには次が含まれます。
- 各エンティティ型に主キー プロパティを追加する。
- 1 つのエンティティ型に外部キー プロパティを追加する。
- エンティティ型間の参照を主キーと外部キーと関連付けて、単一のリレーションシップ構成を形成します。
このマッピングが行われると、EF は、オブジェクト間の参照が変更されたときに必要に応じて外部キー値を変更し、外部キー値が変更されたときに必要に応じてオブジェクト間の参照を変更します。
Note
主キーは、マッピング 関係以上に使用されます。 詳細については、「キー」を参照してください。
たとえば、上記のエンティティ型は、主キープロパティと外部キー プロパティを使用して更新できます。
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; }
}
ヒント
主キー プロパティと外部キー プロパティは、エンティティ型のパブリックに表示されるプロパティである必要はありません。 ただし、プロパティが非表示の場合でも、EF モデルにまだ存在することを認識することが重要です。
、Blog.Id
、および の外部キー プロパティのBlog
主キー プロパティは、エンティティ型Blog.Posts
( と Post.Blog
) の間のPost
Post.BlogId
参照 ("ナビゲーション") に関連付けることができます。 これは、このような単純なリレーションシップを構築するときに EF によって自動的に行われますが、 の DbContext
メソッドをオーバーライドするときにOnModelCreating
明示的に指定することもできます。 次に例を示します。
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);
}
これらのプロパティはすべて、 と の間 Blog
の単一のリレーションシップの表現として一貫して動作します Post
。
詳細は以下のページをご覧ください
EF では、さまざまな種類のリレーションシップがサポートされており、これらのリレーションシップをさまざまな方法で表現および構成できます。 さまざまな種類のリレーションシップの例については、次を参照してください。
- 1 対多のリレーションシップ。1 つのエンティティが他の任意の数のエンティティに関連付けられます。
- 1 対 1 のリレーションシップ。1 つのエンティティが別の 1 つのエンティティに関連付けられます。
- 多対多リレーションシップ。任意の数のエンティティが他の任意の数のエンティティに関連付けられます。
EF を初めて使用する場合は、上記の箇条書きでリンクされている例を試して、リレーションシップがどのように機能するかを確認する良い方法です。
リレーションシップ マッピングに関連するエンティティ型のプロパティを詳しく調てるには、次を参照してください。
- リレーションシップ内の外部キーとプリンシパル キー。外部キーがデータベースにマップされる方法について説明します。
- リレーションシップ ナビゲーション。リレーションシップのオブジェクト指向ビューを提供するために、ナビゲーションを外部キーに重ねて表示する方法について説明します。
EF モデルは、規則、マッピング属性、モデル ビルダー API という 3 つのメカニズムの組み合わせを使用して構築されます。 ほとんどの例では、モデル構築 API を示しています。 その他のオプションの詳細については、次を参照してください。
- エンティティ型、そのプロパティ、および型間のリレーションシップを検出するリレーションシップ規則。
- リレーションシップ マッピング属性。リレーションシップ構成の一部の側面に対して、モデル構築 API の代わりに使用できます。
重要
モデル構築 API は、EF モデルの最終的な信頼できるソースです。常に、規則によって検出された構成またはマッピング属性によって指定された構成よりも優先されます。 EF モデルのすべての側面を構成するための完全な忠実性を備えた唯一のメカニズムでもあります。
リレーションシップに関連するその他のトピックは次のとおりです。
- 連鎖削除。 または
SaveChangesAsync
の呼び出し時SaveChanges
に関連エンティティを自動的に削除する方法を示します。 - 所有されるエンティティ型 では、特別な種類の "所有" リレーションシップが使用されます。これは、ここで説明する "通常" リレーションシップよりも 2 つの型間の接続が強くなっていることを意味します。 通常のリレーションシップに関してここで説明する概念の多くは、所有リレーションシップに引き継がれている。 ただし、所有されるリレーションシップには、独自の特別な動作もあります。
ヒント
使用される用語の理解に役立つドキュメントを読む場合は、必要に応じて関係用語の 用語集 を参照してください。
リレーションシップの使用
モデルで定義されたリレーションシップは、さまざまな方法で使用できます。 次に例を示します。
- リレーションシップを使用すると、次の 3 つの方法のいずれかで 関連データに対してクエリを実行 できます。
- リレーションシップは、PK 値と FK 値の照合を通じて データ シード処理 で使用できます。
- リレーションシップを使用して 、エンティティのグラフを追跡できます。 その後、リレーションシップは変更トラッカーによって次の用途に使用されます。
- リレーションシップの変更を検出し、修正を実行する
- または を使用して外部キーの更新をデータベースに
SaveChanges
送信するSaveChangesAsync