Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database design 如何处理数据库中的多态性?_Database Design_Oop - Fatal编程技术网

Database design 如何处理数据库中的多态性?

Database design 如何处理数据库中的多态性?,database-design,oop,Database Design,Oop,范例 我有人、特殊人和用户Person和SpecialPerson都是人——他们在网站上没有用户名或密码,但他们存储在数据库中以备记录。用户拥有与Person和潜在的SpecialPerson相同的所有数据,以及在网站注册时的用户名和密码 你将如何解决这个问题?您是否有一个Person表来存储一个人的所有公共数据,并使用一个键在SpecialPerson(如果他们是特殊的人)和User(如果他们是用户)中查找他们的数据,反之亦然?我个人将把所有这些不同的用户类存储在一个表中。然后,您可以有一个

范例

我有
特殊人
用户
Person
SpecialPerson
都是人——他们在网站上没有用户名或密码,但他们存储在数据库中以备记录。用户拥有与
Person
和潜在的
SpecialPerson
相同的所有数据,以及在网站注册时的用户名和密码



你将如何解决这个问题?您是否有一个
Person
表来存储一个人的所有公共数据,并使用一个键在
SpecialPerson
(如果他们是特殊的人)和User(如果他们是用户)中查找他们的数据,反之亦然?

我个人将把所有这些不同的用户类存储在一个表中。然后,您可以有一个存储“Type”值的字段,也可以通过填写哪些字段来暗示您正在处理的是哪种类型的人。例如,如果UserID为NULL,则此记录不是用户

您可以使用一对一或无类型的联接链接到其他表,但在每个查询中都将添加额外的联接


如果您决定走这条路线(他们称之为“每个层次结构的表”或“TPH”),LINQ到SQL也支持第一种方法。

过去,我完全按照您的建议来做——为普通内容创建一个Person表,然后为派生类创建SpecialPerson链接。但是,我在想,因为Linq2Sql希望在同一个表中有一个字段,这表明了差异。不过,我并没有过多地研究实体模型——很确定这允许使用另一种方法

是的,如果可能有更多类型,我也会考虑一个Type ID和一个HyfType表。然而,如果只有3个,那就不应该是nec

如果用户、个人和特殊个人都有相同的外键,那么我将有一个表。添加名为Type的列,该列被约束为用户、个人或特殊人员。然后根据Type的值对其他可选列进行约束


对于目标代码来说,如果有单独的表或多个表来表示多态性,则没有多大区别。但是,如果您必须对数据库执行SQL,那么如果多态性被捕获到单个表中,那么就容易多了……前提是子类型的外键相同

我想说的是,根据人和特殊人的区别,你可能不希望这个任务有多态性

我将创建一个用户表,一个对用户具有可为空外键字段的人员表(即,该人员可以是用户,但不一定是用户)。

然后我会制作一个特殊的Person表,该表与Person表相关,其中包含任何额外的字段。如果在SpecialPerson中存在给定Person.ID的记录,则他/她/它是一个特殊的人。

通常有三种方法将对象继承映射到数据库表

您可以创建一个大表,其中包含所有对象的所有字段,并为该类型指定一个特殊字段。这很快,但浪费了空间,尽管现代数据库通过不存储空字段来节省空间。如果您只查找表中的所有用户,那么每种类型的用户都会很慢。并不是所有的地图绘制者都支持这一点

您可以使用包含基类字段的所有表为所有不同的子类创建不同的表。从性能角度来看,这是可以的。但不是从维护的角度。每次基类更改时,所有表都会更改

你也可以像你建议的那样,为每门课做一张桌子。这样,您需要连接来获取所有数据。所以它的性能较差。我认为这是最干净的解决办法


你想用什么当然取决于你的情况。没有一个解决方案是完美的,因此您必须权衡利弊。

我在这里要说的是将数据库架构师派到conniptions,但这里是:

将数据库视图视为接口定义的等价物。 表是类的等价物

因此,在您的示例中,所有3人类都将实现IPerson接口。 因此,您有3个表-分别对应“用户”、“个人”和“特殊人”

然后有一个视图“PersonView”或任何选择公共属性(由“接口”定义)的视图,从所有3个表中选择到单个视图中。 在此视图中使用“PersonType”列存储所存储人员的实际类型


因此,当您运行可以对任何类型的人进行操作的查询时,只需查询PersonView视图

在关系数据库中处理继承有三种基本策略,根据您的具体需要,还有许多更复杂/定制的替代方案

  • 每个类层次结构的表。一个表用于整个层次结构
  • 每个子类的表。为每个子类创建一个单独的表,子类表之间的关联为0-1
  • 每种混凝土等级的表。为每个具体类创建一个表

这些方法中的每一种都提出了自己关于规范化、数据访问代码和数据存储的问题,尽管我个人的偏好是每个子类使用表,除非有特定的性能或结构原因使用其中一种替代方法。

冒着成为“建筑宇航员”的风险,我更倾向于为子类使用单独的表。使子类表的主键也成为链接回超类型的外键

这样做的主要原因是,这样做在逻辑上更加一致,并且对于特定的记录,不会有很多字段是空的和无意义的。在迭代设计过程时,此方法还可以更轻松地向子类型添加额外字段

这个
PERSON (personid,persontype, name,address, phone, XMLOtherProperties)
 public string StrangeProperty
{
get { return XMLPropertyBag["StrangeProperty"];}
set { XMLPropertyBag["StrangeProperty"]= value;}
}