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;}
}