上篇部落格《我們該如何設計資料庫(三)》寫出來之後,深感自己寫得不夠清晰,虎頭蛇尾,描述問題用了很多篇幅,而問題的解決方案及其優缺點卻是一筆帶過,於是就寫下了這篇部落格來負荊請罪。
範例程式碼下載:點擊這裡下載
範例程式碼說明見下文
首先讓我們來回顧一下《我們該如何設計資料庫(三)》中描述的問題:
現在有一個系統,我們暫時假設為學校選課系統。
系統要按學校來賣。每個學校的選課邏輯都是一樣的,而表中的資料有共性,但是也有差異性。比如說基本的Teacher表結構是這樣的:
現在把系統賣給A學校。A學校除了的Teacher表除了使用者名稱和密碼之外,還要儲存老師的FirstName和LastName,那麼表結構變化如下:
現在B學校也買了我們的系統。他們的Teacher表不要FirstName和LastName,但是要儲存教師的工號“Number”,表結構如下:
好,現在我們的問題出來了:怎麼去解決這種差異性
大致有3種解決方案
1、表中加冗餘
2、增加冗餘表
3、model繼承
第一種思路:表中加冗餘,在上篇已經分析過了,在此就稍微說一下優缺點。
優點在於簡單:思路簡單,實現也簡單
缺點在於維護困難:①如果我們的系統賣了很多所學校,那麼對於系統維護人員來說,這是一場噩夢 ②違背開閉:每次加欄位都要去修改已有Model
第二種思路:增加冗餘表
如上一篇文章中徐少俠所言,我們也可以這樣來設計,用一張冗餘表來儲存差異欄位,:
FirstName、LastName、Number對應擴充表內的三行。
這樣的好處在於:思路簡單,實現相比第一種思路複雜一些,但是也不算複雜。
缺點在於:①Join 。
②違背開閉:每次加欄位都要去修改已有Model。
徐少俠在留言中也說了缺點:查詢資料時候比較辛苦.只能用在讀寫壓力不高的地方.)
第三種思路:Model繼承
這種方法,比較適合使用ORM,或者說適合有Code First的ORM。
在這裡使用的是EF5EF5推薦環境是.NET 4.5,不過.NET 4也無傷大雅)
- public class Identifier
- {
- [Key]
- public int ID { get; set; }
- }
-
- public interface Contact
- {
- string Phone { get; set; }
- string Email { get; set; }
- }
-
- public class TeacherBase : Identifier, Contact
- {
- [StringLength(50)]
- public string UserName { get; set; }
-
- [StringLength(50)]
- public string Pwd { get; set; }
-
- [StringLength(50)]
- public string Phone { get; set; }
-
- [StringLength(50)]
- public string Email { get; set; }
- }
這樣就是我們的Teacher基礎資料表。
那麼我們的系統賣給我A學校,A學校Teacher表有兩個自己的差異欄位:FirstName,LastName。那麼Model就要這樣寫。
- namespace Model.A
- {
- public class Teacher : TeacherBase
- {
- [StringLength(50)]
- public string FirstName { get; set; }
-
- [StringLength(50)]
- public string LastName { get; set; }
- }
- }
產生出來的資料庫
然後又把系統賣給了B學校。B學校系統的部署是獨立的。B學校Teacher表差異欄位為Number:
- namespace Model.B
- {
- public class Teacher : TeacherBase
- {
- [StringLength(50)]
- public string Number { get; set; }
- }
- }
產生出來的資料庫