2010-11-05 88 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