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)

然后我的插入可能会通过外部看起来像每个子表的正常 CRUD 过程,但在内部插入DrivableEntity然后使用范围标识插入到预期的表中。

作为一名程序员而不是数据建模者,这让我开始思考对象继承。对于直接继承,这很棒。通用数据/任务可以抽象一个级别,可以维护 Liskov 替换等。但是数据模型中是否可以进行多重继承?

我主要是 C# 开发人员,所以我开始考虑接口。如果我想公开“实现”IDrivable和/或ITowable等的表怎么办。这样的事情可能吗?有没有人做过类似的事情?

4

4 回答 4

1

大卫,

实体框架具有使用继承的能力。这是对实体框架中继承的很好的概述。您可以将 POCO 与 EF 结合使用来创建自己的接口以提供对数据的访问。

您描述的情况并不是真正的多重继承,因为您有一个基表/实体和派生表/实体。要在 EF 中对此进行建模,您需要创建一个基础实体,然后创建每个子实体。此时,您可以将每种类型的子实体属性映射到正确的表。

话虽如此,您的插入/更新/删除逻辑将变得非常复杂。实体框架可能会遇到复杂模型的问题。

我的问题是,你为什么要这样做?如果要在类型之间共享公共数据,我建议在服务器上创建将父表与子表连接起来的视图。它会更快,并且您可以使用而不是触发器来处理 CUD(创建/更新/删除)操作,这将使 SQL 更容易,因为数据访问和数据存储之间存在明显的区别。

这有意义吗?

埃里克

于 2010-11-05T19:06:46.787 回答
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
于 2010-11-05T19:26:13.293 回答
0

您可以创建视图来解决此问题。

视图可驾驶汽车视图Drivabale自行车
视图
拖车

然后将视图组合成一个超级视图,使用联合将可驱动和可牵引实体组合在一起。您只能包含两者中共有的那些列。类似但不同的名称需要标准化:

CREATE VIEW vrDiveTow
AS

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

UNION

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

一个大问题。SQL 使用可以缓存的查询计划来产生结果。如果 SQL 的查询计划是围绕查询“Seven-Up”而构建的,并且您正在过滤“Coke”,那么查询计划是无效的,并且实际上会使用全表扫描。

于 2010-11-06T13:02:59.977 回答
0

子类型化是可能的,但也不鼓励。数据库是他们自己的世界,你不应该尝试将 OOP 原则带入那个世界。许多人尝试过,许多人失败了。如果您尝试用 OOP 术语来考虑数据库“对象”,您的数据库将会受到影响。

于 2010-11-06T15:23:39.463 回答