2010-09-09 102 views
4

我想弄清楚的是爲對象模型的繼承關係映射到關係型數據庫的最佳方式。例如考慮以下類結構。貯藏繼承的對象在數據庫中

public Class Item 
{ 
    public String Name{get; set;} 
    public int Size {get; set}  
} 

public Class Widget:Item 
{ 
    public String Color{get; set;} 
} 

public Class Doohicky:Item 
{ 
    public String Smell{get; set;} 
} 

下面是我正在考慮如何將此結構保存到數據庫的幾個選項。

選項1:所有項目類型

Items Table: ItemID, Name, Color, Smell 

這吮吸,因爲它需要NULL值單桌。

選項2:爲每個項目類型

Widgets Table: WidgetID, Name, Color 
Doohicky Table: DoohickyID, Name, Smell 

這是更好的,但是會比較困難,列出所有項目單獨的表

選項3:鏈接表

Items Table: ItemID (PK), Name, Size 
Widgets Table: WidgetID (PK), ItemID (FK), Color 
Doohicky Table: DoohickyID (PK), ItemID (FK), Smell 

我認爲這個選項是最好的,因爲它阻止我在任何空值字段,再加上它可以更容易地列出所有的項目,和/或創建一個特定類型的項目(小工具或Doohickies)列表。

但是,我不知道如何創建項目表和窗口小部件和Doohickies表之間的關係。我不想結束在任何表中引用Items表中的相同ItemID的行。

例如,當我添加到窗口小部件表中的條目,我怎麼能確保其鏈接到項目表具有獨特的ItemID的新條目?我是否應該只跟蹤ItemID而不是像WidgetID和DoohickyID那樣分離類型特定的ID,並使用它來創建Items表和類型特定表之間的一對一關係?

選項4

Items Table: ItemID (PK), Name, Size 
Widgets Table: ItemID (PK), Color 
Doohicky Table: ItemID (PK), Smell 

回答

6

你描述Single-Table InheritanceConcrete Table InheritanceClass Table Inheritance

見很多關於他們的信息經典Martin Fowler的書Patterns of Enterprise Application Architecture

你可以做的一件事是確保只有一個子類型可以引用超類型,即使用ItemType字段。外鍵可以引用UNIQUE約束的列以及PRIMARY KEY。因此,您可以添加Items.ItemType並對ItemID,ItemType進行唯一限制。每個子類型表中的外鍵引用這個兩列唯一鍵。然後,您可以將每個子類型表中的ItemType限制爲某個值。然後它必須匹配超類型表中的值,該值只能有一個值。

Items Table: ItemID (PK), ItemType, Name, Size 
    UNIQUE: (ItemID, ItemType) 
Widgets Table: ItemID (PK), ItemType, Color 
    FK: (ItemID, ItemType) 
    CHECK: ItemType=W 
Doohicky Table: ItemID (PK), ItemType, Smell 
    FK: (ItemID, ItemType) 
    CHECK: ItemType=D 
+0

啊這有助於很多。我當然想遵循「類表繼承」模式。 – 2010-09-14 22:31:33

0

你有沒有考慮一個NoSQL解決像RavenDBMongoDB?如果您的需求不純粹是關係型的,非關係型解決方案可能會大大簡化。

0

如果你正在設計保持當前類,我寧願你的選項3作爲上述原因的首選選項。

重新您有關查詢:

However, I'm not sure how to create the relationship between the Items table and the 
Widgets and Doohickies tables. I don't want to end up with row in either table 
referencing the same ItemID in the Items table. 

比爾的建議之上,絕對是一個不錯的選擇。東西我沒有想到:-)然而,我認爲它的關係,你可以在你的應用程序代碼本身或通過使用插入觸發器強制執行。

然而我關心的是試圖模擬數據庫級別的繼承本身。

如果子類的數量預計會在一段時間內增長,那麼這種類型的DB設計可能變得非常難以維護。

除了:

Items Table: ItemID (PK), Name, Size   
Widgets Table: WidgetID (PK), ItemID (FK), Color   
Doohicky Table: DoohickyID (PK), ItemID (FK), Smell   

什麼是新類的情形產生像下面獲取添加?

DontDoHicky Table : DoohickyID (PK), ItemID (FK), Smell, **TASTE**   
MidWidget Table : WidgetID (PK), ItemID (FK), Color , **Height**   
MidDoHicky Table : WidgetID (PK), ItemID (FK), **Height**, **Smell** 

這當然是經典的OO繼承問題。 如果您希望在一段時間來成長像這樣的應用,也許需要事先計劃一下,並在數據庫級別,你可能更喜歡去一個更通用的方法

Items Table: ItemID (PK), Name, Size, **ItemType**   
**ItemAttributes Table : ItemID (PK), AttributeID, AttributeName, AttributeValue**  

這將允許你只要符合標準,就可以輕鬆地實施1:1映射的約束,並允許使用AttributeName輕鬆查詢所有屬性。

這可能是老式的方法,不是非常面向對象,但它可能更適合未來的靈活性。