本檔提供物件模型和關係資料庫中關聯性的表示法的簡單簡介,包括 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; }
}
同樣地,相同關聯性的相反方向可以表示為每個 Post上的物件集合Blog:
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 中的「關聯性」。
重要
單一關聯性通常可以雙向遍歷。 在此範例中,即從 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 外鍵數據行所參考。 此欄位是「受限於」,因此BlogId欄位中的任何Posts值都必須匹配Id欄位中的Blogs值。 此比對會決定每個文章與哪個部落格相關。 例如,如果 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 和 Blog.Id 的主鍵屬性,以及 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);
}
現在,所有這些屬性都會以一致的方式一起運作,以表示 和Blog之間的Post單一關聯性。
深入了解
EF 支援許多不同類型的關聯性,其中有許多不同方式可以表示和設定這些關聯性。 若要跳到不同類型的關聯性的範例,請參閱:
如果您不熟悉 EF,那麼嘗試上面提到的連結範例是了解關聯性運作方式的好方法。
若要深入瞭解關聯性對應所涉及的實體類型屬性,請參閱:
EF 模型是使用三種機制的組合來建置:慣例、對應屬性和模型產生器 API。 大部分範例都會顯示模型建置 API。 若要深入瞭解其他選項,請參閱:
重要
模型建置 API 是 EF 模型的最終事實來源,它一律優先於慣例或對應屬性所指定的組態。 這也是唯一具有完整精確度的機制,可設定EF模型的各個層面。
與關聯性相關的其他主題包括:
-
串聯刪除,描述如何在呼叫
SaveChanges或SaveChangesAsync時自動刪除相關的實體。 - 擁有的實體類型 會使用特殊的「擁有」關聯性類型,這表示這兩種類型之間的連線比這裡所討論的「一般」關聯性更強。 描述正常關聯性的許多概念也適用於擁有權關聯性。 歸屬的關係也有其特定的行為。
使用關聯性
模型中定義的關聯性可以用各種方式使用。 例如:
- 關聯性可用來 以下列三種方式中的任何一種方式查詢相關數據 :
- 關聯可以在數據植入中,透過比對 PK 值與 FK 值來使用。
- 關聯性可用來追蹤與實體相關的圖形。 變更追蹤器接著會使用關聯性來:
- 偵測關聯性中的變更並執行修正
-
將外鍵更新發送至資料庫
SaveChanges或SaveChangesAsync