關聯性的簡介
本檔提供物件模型和關係資料庫中關聯性的表示法的簡單簡介,包括 EF Core 在兩者之間的對應方式。
物件模型中的關聯性
關聯性定義兩個實體彼此的關聯性。 例如,在部落格中建立文章模型化時,每個文章都會與其發佈的部落格相關,而部落格則與該部落格上發佈的所有文章有關。
在 C# 之類的面向物件語言中,部落格和文章通常以兩個類別表示: Blog
和 Post
。 例如:
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; }
}
在上述類別中,沒有任何可指出 Blog
和 Post
相關的專案。 這可以加入至物件模型,方法是將參考從 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; }
}
從和 Post
反轉Blog
Post
的這個連接Blog
稱為 EF Core 中的「關聯性」。
重要
單一關聯性通常會以任一方向周遊。 在此範例中,即從 Blog
到 Post
透過 Blog.Posts
屬性,以及從 Post
回到 Blog
Post.Blog
屬性。 這是 一個 關聯性,而不是兩個。
提示
在 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
數據表都會獲得「主鍵」數據行。 主鍵的值可唯一識別每個文章或部落格。 此外, Posts
數據表也會提供「外鍵」數據行。 主 Blogs
鍵數據行 Id
是由 BlogId
數據表的 Posts
外鍵數據行所參考。 此數據行為「限制」,因此的數據Posts
行中的任何BlogId
值都必須符合 數據行Blogs
中的Id
值。 此比對會決定每個文章與哪個部落格相關。 例如,如果 BlogId
數據表的一個數據列中 Posts
的值是 7,則該數據列所代表的文章會以主鍵 7 發佈在部落格中。
在 EF Core 中對應關聯性
EF Core 關聯性對應全都與將關係資料庫中所使用的主鍵/外鍵表示法對應至物件模型中所用對象之間的參考。
從最基本的意義上說,這牽涉到:
- 將主鍵屬性新增至每個實體類型。
- 將外鍵屬性新增至一個實體類型。
- 將實體類型與主鍵與外鍵之間的參考產生關聯,以形成單一關聯性組態。
進行此對應之後,EF 會在對象之間的參考變更時視需要變更外鍵值,並在外鍵值變更時視需要變更對象之間的參考。
注意
主鍵用於對應關聯性以上。 如需詳細資訊,請參閱 密鑰 。
例如,上述實體類型可以使用主鍵和外鍵屬性來更新:
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
外鍵屬性Post
Post.BlogId
,然後可以與實體類型 (Blog.Posts
和Post.Blog
) 之間的參考 (“navigations”) 相關聯。 這樣建置簡單的關聯性時,EF 會自動完成這項作業,但在覆寫 OnModelCreating
的 DbContext
方法時也可以明確指定。 例如:
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);
}
現在,所有這些屬性都會以一致的方式一起運作,以表示 和Post
之間的Blog
單一關聯性。
深入了解
EF 支援許多不同類型的關聯性,其中有許多不同方式可以表示和設定這些關聯性。 若要跳到不同類型的關聯性的範例,請參閱:
如果您不熟悉 EF,則嘗試上述項目符號點中連結的範例是了解關聯性運作方式的好方法。
若要深入瞭解關聯性對應所涉及的實體類型屬性,請參閱:
EF 模型是使用三種機制的組合來建置:慣例、對應屬性和模型產生器 API。 大部分範例都會顯示模型建置 API。 若要深入瞭解其他選項,請參閱:
重要
模型建置 API 是 EF 模型的最終事實來源,它一律優先於慣例或對應屬性所指定的組態。 這也是唯一具有完整精確度的機制,可設定EF模型的各個層面。
與關聯性相關的其他主題包括:
- 串聯刪除,描述呼叫 或
SaveChangesAsync
時SaveChanges
,如何自動刪除相關的實體。 - 擁有的實體類型 會使用特殊的「擁有」關聯性類型,這表示這兩種類型之間的連線比這裡所討論的「一般」關聯性更強。 這裡為正常關聯性描述的許多概念會延續到擁有的關聯性。 然而,擁有的關係也有他們自己的特殊行為。
提示
使用關聯性
模型中定義的關聯性可以用各種方式使用。 例如:
- 關聯性可用來 以下列三種方式中的任何一種方式查詢相關數據 :
- 使用
Include
積極作為LINQ查詢的一部分。 - 延遲使用延遲載入 Proxy,或延遲載入而不使用 Proxy。
- 明確 使用
Load
或LoadAsync
方法。
- 使用
- 關聯性可以透過比對 PK 值與 FK 值,在數據植入中使用。
- 關聯性可用來 追蹤實體的圖表。 變更追蹤器接著會使用關聯性來:
- 偵測關聯性中的變更並執行修正
- 使用
SaveChanges
或將外鍵更新傳送至資料庫SaveChangesAsync