在實際的應用場景中,兩個實體之間不只是簡單的一對一關係,還會出現多對多關係,同時還有可能會出現多對多關係還附帶有其他欄位的情況。本文通過幾個例子,對錶間多對多關係的實體類代碼表示方法進行描述。這種設計方法,並不只是在使用 ORM 框架時需要,事實上,它是 POCO 及簡單 Java 類(POJO)的... ...
介紹
在之前的 Entity Framework 快速上手介紹 之中,兩個實體之間只是簡單的一對一關係,而在實際的應用場景中,還會出現多對多關係,同時還有可能會出現多對多關係還附帶有其他欄位的情況。
下麵以幾個例子,對表間多對多關係的類表示加以更加詳細地描述。雖然兩個場景舉例是使用的 C# 及 Entity Framework(Model First) 框架自動生成資料庫、實體類。但這種設計方法,並不只是在使用 ORM 框架時需要,事實上,它是 POCO 及簡單 Java 類(POJO)的設計原則之一。
場景實例
場景一
在考慮多對多關係還附帶有欄位的情況之前,讓我們先看一下,多對多關係但不附帶額外欄位的情況下,實體類代碼的表示。
此處使用 Entity Framework(Model First),快速將 model diagram 轉為資料庫中的表及實體類。
假設的場景是學生選課,一名學生可以選多門課,一門課也可以被多個學生選擇。E-R 圖如下所示:
對應自動生成的資料庫如下:
- StudentSet
- CourseSet
- CourseRegistrationSet
- 其中 Course_Id 與 Students_Id(註:此處詞尾(s)負數的原因參見上面 E-R 圖中右邊的 Properties 中 End1 Navigation Property 的設置)分別以另外兩張數據表的 Id 主鍵作為外鍵。
- 同時 Course_Id與 Students_Id 兩者聯合做 CourseRegistrationSet 表的主鍵。
對應自動生成實體類的代碼如下:
Student.cs
namespace Model { using System; using System.Collections.Generic; public partial class Student { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public Student() { this.Course = new HashSet<Course>(); } public int Id { get; set; } public string 學號 { get; set; } public string 姓名 { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public virtual ICollection<Course> Course { get; set; } } }
Course.cs
namespace Model { using System; using System.Collections.Generic; public partial class Course { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public Course() { this.Students = new HashSet<Student>(); } public int Id { get; set; } public string 課程名稱 { get; set; } public string 學分 { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public virtual ICollection<Student> Students { get; set; } } }
分析
- 資料庫表之間一對一、一對多的關係在代碼中是通過 對象引用 或 對象數組/List等形式的引用 實現的。
從實例中可以看出,CourseRegistrationSet 表中的多對多關係在代碼中的表現形式同樣是實體類中的 對象List等形式的引用,只不過多對多關係是多個實體類中都存在其他實體類對象List的引用。
場景二
現在讓我們增加一個需求,實際應用之中,資料庫不可能僅僅存儲某學生選了某門課程這些信息,同時還需要保存選課時間、操作人、成績等等信息。
現在讓我們為 CourseRegistrationSet 表增加一個欄位——成績。
- CourseRegistrationSet
同時我們需要更新一下程式中的代碼,這時候問題出現了