2010-01-25 106 views
1

在做一些映射一對一關係的研究時,我遇到了一些讓我質疑我的一些數據庫設計決策的陳述。NHibnerate數據設計建議

基本上我有類似以下一些實體:

人聯繫,家長

兩個觸點和父母都是人。 一個人可能是聯繫人,父母,兩者都不是。

我想出的數據庫設計爲這三個實體中的每一個都有一個表,並且所有三個表共享一個主ID(PersonID)。從數據庫設計的角度來看,這似乎是一種很好的規範化和合理的表現方式來表示數據庫及其關係(至少對我而言)。

此時,我開始編碼C#類和NHibnerate映射來表示這些實體。我能找到的最自然的映射方法是使用映射。其他選項(一對一,一對多等)似乎要求我在表中添加一個或多個不必要的FK。在通過NHibernate的文檔瀏覽我偶然發現瞭如下聲明:

此功能常常對遺留數據模型有用,我們推薦比類和細粒度的領域模型表少。但是,如稍後所解釋的,在單個層次結構中的繼承映射策略之間進行切換非常有用。

我的問題是:

A)我是不是違反本校長? B)如果是這樣,我會如何更好地設計這個系統?

這段陳述是否暗示我應該將所有Person/Contact/Parent字段合併到一個表中(帶有許多可爲空的字段)?或者我不知何故錯過了這一點?

由於這是一個罕見的場合,我可以從頭開始設計表格/類,所以我想說得對。先謝謝您的幫助!

編輯:我是如何打算的上述數據庫設計更多信息工作:

的基本思路是,每個人得到的人表中的記錄。相關表中記錄的存在/不存在決定了這個人是否是家長,聯繫人等......這似乎強制執行一對多關係並允許快速查詢/連接(共享主ID是在每個表中聚集PK)。

編輯:謝謝你們的幫助。當我設計這個系統時,我並沒有真正考慮到查詢能力,所以我將轉向類似於Jamie Ide & hlgem建議的解決方案。我發現所有的答案有幫助。總而言之,共享主鍵看起來會導致c#端的對象模型出現一些問題。

回答

1

其中一些取決於您打算如何查詢該數據。如果您想要輕鬆地查看某個人扮演角色的特定角色的角色,請製作角色表。要查看一個人的所有角色,無論您稍後添加了多少角色,只需要連接兩個表。否則,你必須加入到每一個專業表(左聯接,如果他們不存在),只是爲了看看一個人有什麼作用。表現不佳。

在我們的數據庫中有很多這種類型的關係,我們有一個帶有id的人員表,一個帶有id和角色ID的角色表,以及一個查找角色的角色類型表。然後是具有特定角色信息的專業表,如銷售代表或銷售目標。每個表都有它自己的id,每個表(除查找表外)都包含來自person表的id,它被設置爲外鍵。 (相信我很少有這樣的事情,因爲不必要的外鍵,反過來是不正確的,當你應該有一個壞消息時錯過了FK。)

現在你仍然可以使用外鍵關係PK從父表中作爲Fk到人表以及專業表的PK,但我建議不要這樣做。無論如何,如果您沒有爲人員表設置FK,那麼您的數據就註定會出現數據完整性問題。我更喜歡使用代理鍵,因此總是在每張桌子上設置自己的密鑰。它從長遠來看可以防止很多重新設計問題。如果你想保持一對一的關係,那麼只需要一個簡單的唯一索引就可以了。表格從一對一移動到一對多,你需要做的就是放棄索引。如果你也使用它作爲你的PK,那麼你需要一個新的PK,並且所有參考PK的代碼都必須改變。將一個新的PK添加到一個包含150,000,000條記錄的表中,而不是一項有趣的任務。

2

您的數據庫設計需要一些工作;這是我的建議。

這很好,你有這樣的想法,聯繫人和父母都可以是人;但是,您需要聯繫人和父母才能擁有不同的主鍵。您可以強制要求他們都具有Parent ID,並在Contact表和父表中引用Person表中的條目的Person ID並具有不可爲空的外鍵。

所以Person表應該有一個唯一的主鍵(它的ID)和任何其他相關的列。聯繫人表應具有其自己的唯一主鍵(其ID),對Person表的不可空的外鍵引用(Person表中的ID)以及任何其他相關列。父表應具有其自己唯一的主鍵(其ID)以及對Person表(Person表中的ID)以及任何其他相關列的不可爲空的外鍵引用。

這應該解決您的映射問題。如果您需要,您可以使用視圖「重新組合」您的人員/家長/聯繫人「星座」(相關表格的集合)。

+0

謝謝你的建議。我同意這會解決我的映射問題。但是,我認爲這使得數據庫設計方面「更醜陋」。由於所有這些關係都應該是一對一的(也許我應該在第一篇文章中明確說明),您的建議似乎會在模型中引入大量不必要的FK。除此之外,它使關係成爲一個>多個而不是一個>一個 - 最初的設計會強制執行正確的基數。 – Krazzy 2010-01-25 19:23:53

+0

@Krazzy:說實話,在不瞭解表格範圍的情況下建議設計有點困難;因爲我不知道Person,Parent和Contact有多少列,所以很難說出什麼是好的設計。根據您的反饋,也許您最好將Parent和Contact表與Person表合併,並根據需要使用View來恢復父級和聯繫人? (這基本上是我原來的建議的反面...) – 2010-01-25 20:39:43

+0

@Krayzzy:無論如何,基本問題是共享主鍵。一個很好的通用規則(以及Hibernate廣泛使用的規則)是爲每個表都有一個不同的主鍵。 – 2010-01-25 20:41:04

1

你在問繼承映射,而不是一對一的關係。您的設計需要table-per-subclass映射,但我不確定如何解決人員既可以是聯繫人又可以是父母的要求。我不知道一個好的方法來模擬這個,除了引入另一個涵蓋兩個角色的子類。這樣想一下,如果您要求您的存儲庫返回一個人,並且該人既是聯繫人又是父級,那麼應該返回哪種類型?

如果你堅持繼承子類,那麼我會建議堅持table-per-class如果可能的話。

但是更好的設計可能是引入一個「角色」表,並且在Person和Role之間具有一對多的關係。

編輯補充:恕我直言,你目前的設計將無法正常工作。什麼類型的對象代表既是聯繫人又是父母的人?

您可以使用包含附加數據的「複雜」角色表來代替簡單的角色表。您可以擁有一組角色對象(ContactRole,ParentRole等),每個對象都包含與該角色相關的字段。一個Person對象將有一個Role對象的集合。

+0

感謝您的建議。由於你提到的原因,繼承不是一種選擇。此外,將來可能會引入更多類型的「人員」,從而引入了一個子類來處理每個可能性很大的問題。一個簡單的角色表不會工作,因爲每個「角色」都需要該角色唯一的關聯數據。 – Krazzy 2010-01-25 19:45:31

+0

@Krazzy:我編輯了我原來的答案,希望它有幫助。 – 2010-01-25 20:03:54

+0

再次感謝您的幫助 - 目的是在相關表格中存在/不存在記錄將指示某個人是否屬於給定類型。因此,對於既是聯繫人又是父母的人員,個人,聯繫人和家長的記錄將出現在相應的表格中。 – Krazzy 2010-01-25 20:15:03