2010-11-05 93 views
1

這個問題可能有一個簡單的答案,這是一個標準的做法,或者沒有答案,因爲它不能做簡單的原因,或者只是一個有趣的思考練習。我目前正在坐在最後一個選項,但希望第一個...Supertyping表 - 是否可以實現多重繼承?

比方說,我想要在我的數據模型中創建一個「組」或「類」的實體。一般情況下,我會使用一個超表是這樣的:

DrivableEntity 
---------- 
ID (PK, auto-increment) 
Type (int or otherwise some kind of enum) 

Car 
---------- 
ID (PK, FK to DrivableEntity) 
(car-specific fields) 

Bike 
---------- 
ID (PK, FK to DrivableEntity) 
(bike-specific fields) 

然後,我的刀片可能會經過哪些外部看起來像每個子表正常的CRUD的程序,但在內部插入到DrivableEntity,然後使用範圍身份插入到預定的表格中。

作爲程序員而不是數據建模師,這讓我想到了對象繼承。對於直接繼承來說,這很好。常見的數據/任務可以抽象到一個級別,Liskov Substitution可以維護等等。但是,在數據模型中可以實現多重繼承嗎?

我主要是C#開發人員,所以我開始考慮接口。如果我想暴露「實施」IDrivable和/或ITowable等的表格是什麼情況?有沒有人做過類似的事情?

回答

1

一般有兩種方法對數據模型工作做好了你所描述的。

您已經描述的模型是其中一種方法,並且具有非常「整潔」的優點。如果表中有大量的列,它的工作效果特別好,因此單個對象的大小不會太大或太大。

DrivableEntity 
---------- 
ID (PK, auto-increment) 
Type (int or otherwise some kind of enum) 

Car 
---------- 
ID (PK, FK to DrivableEntity) 
(car-specific fields) 

Bike 
---------- 
ID (PK, FK to DrivableEntity) 
(bike-specific fields) 

另一種方法是將所有列都保留在一個表中,並用類型指示器標記​​每一行。這種方法可以快速得到混亂,但對簡單情況的開銷要少得多。

只需將其他外鍵列添加到其中一個「派生」實體,即可在原始模型中爲繼承或接口建模。例如:

FlyableEntity 
------------- 
ID (PK) 
... flyable attributes 

FlyingCar (implements/inherits IDrivable and IFlyable) 
------------- 
DrivableEntityID (PK, FK) 
FlyableEntityID (PK, FK) 
... add flying car attributes 

or: 

FlyingCar (inherits from Car) 
------------- 
CarID (PK, FK) 
FlyableEntityID (FK) 
... add flying car attributes 
+0

絕對不像我期待的那樣優雅,但在邏輯上它確實適合。我認爲我真正想要做的僅僅是在像SQL Server這樣的關係模型中不可行。不過,這種方法對於該項目仍然可能有用。謝謝! – David 2010-11-06 12:56:00

1

David,

實體框架有能力使用繼承。 This is good overview of inheritance in the Entity Framework。您可以在EF上使用POCO來創建您自己的接口來提供對數據的訪問。

您描述的情況並不是真正的多重繼承,因爲您有一個基本表/實體和派生表/實體。要在EF中對此進行建模,請創建一個基礎實體,然後創建每個子實體。此時,您可以將每種類型的子實體屬性映射到正確的表中。

就這麼說,你的插入/更新/刪除邏輯會變得非常複雜。實體框架可能遇到複雜模型的問題。

我會問的是,爲什麼你這樣做?如果要在類型之間共享公共數據,我建議在服務器上創建與子表連接父表的視圖。它會更快,並且您可以使用instead of trigger來處理CUD(創建/更新/刪除)操作,這將簡化SQL,因爲數據訪問和數據存儲之間存在明顯分離。

這是否有意義?

埃裏克

0

您可以創建視圖來解決此問題。

viewDriveableCar
ViewDrivabaleBike
ViewTowableCar

的意見再結合到結合使用聯合驅動和牽引的實體超視。您只能包含那些在兩者中都很常見的列。類似但不同的名稱將需要規範化:

CREATE VIEW vrDiveTow 
AS 

SELECT 
viewDriveableCar.CarId as ID, 
... other attributes 

UNION 

SELECT 
viewTowableCar.TowableId as ID, 
... other attributes 
UNION 

一大疑難雜症。 SQL使用可以緩存來產生結果的查詢計劃。如果SQL的查詢計劃是圍繞「Seven-Up」查詢的,並且您正在篩選「可樂」,那麼查詢計劃將無效,並且會使用全表掃描。

0

分型是可能的,但也不鼓勵。數據庫是他們自己的世界,你不應該試圖把OOP原則帶入這個世界。許多人嘗試過,許多人都失敗了。如果您嘗試以OOP術語考慮數據庫「對象」,那麼您的數據庫將受到影響。

+0

這也是我得到的感覺。這背後的主要驅動力是DAL在這個項目上的第一個要求是「它不能是ORM」。所以試圖在代碼中推行適當的面向對象原則已經是一場艱苦的戰鬥。 – David 2010-11-06 17:30:56

+0

要求完美無缺。沒有冒犯,但從你的問題/評論中,我感覺你對數據庫不是很熟悉,並且你被迫開發這種解決方案。你真的應該讓一些數據庫開發人員爲你設計數據庫。 – 2010-11-08 11:00:56