我必须为现有应用程序添加功能,并且我遇到了数据情况,我不确定如何建模。我被限制为创建新的表和代码。如果我需要改变现有的结构,我认为我的客户可能会拒绝该提议。虽然如果它是唯一能够做到正确的方法,那么我将不得不这样做。
我有一个Item表,可以链接到任意数量的表,这些表可能会随着时间的推移而增加。该项只能链接到另一个表,但另一个表中的记录可能有很多项链接到它。
链接到的表/实体的示例包括Person
,Vehicle
,Building
,Office
。这些都是单独的表格。
项目示例包括Pen
,Stapler
,Cushion
,Tyre
,A4 Paper
,Plastic Bag
,Poster
,{ {1}}
例如,可以将Decoration"
分配给Poster
或Person
或Office
。将来,如果他们添加Building
表,也可以将其添加到该表中。
我的初步想法是:
Conference Room
Item
{
ID,
Name
}
LinkedItem
{
ItemID,
LinkedToTableName,
LinkedToID
}
字段将允许我在我的代码中标识要链接到的正确表。
我对这个解决方案并不是很满意,但我不能想到其他任何事情。请帮忙! :)
谢谢!
答案 0 :(得分:12)
将表名存储为列值不是一个好习惯。这是一个糟糕的黑客。
有两种标准方法可以完成您要做的事情。第一种称为单表继承。 ORM工具很容易理解这一点,但会进行一些规范化。我们的想法是,所有这些实体 - Person
,Vehicle
,无论如何 - 都存储在同一个表中,每个条目通常有几个未使用的列,以及鉴别器标识实体的类型的字段。
discriminator字段通常是整数类型,映射到代码中的某个枚举。它也可能是数据库中某些查找表的外键,用于标识哪些数字对应于哪些类型(不表名,只是描述)。
另一种方法是多表继承,这对您的数据库更好,但不容易在代码中映射。你可以通过一个基表来定义所有对象的一些常见属性 - 可能只是一个ID和一个名称 - 以及所有“特定”表(Person
等)。使用基本ID作为唯一外键(通常也是主键)。
在第一种情况下,排他性是隐含的,因为所有实体都在一个表中。在第二种情况下,关系在Item
和 base 实体ID之间,这也保证了唯一性。
请注意,对于多表继承,您有一个不同的问题 - 您不能保证只有一个继承表使用基本ID。它可以被几个使用,或根本不使用。这就是为什么多表继承方案通常也有一个鉴别器列,以识别哪个表是“预期的”。同样,此鉴别器不包含表名,它包含一个查找值,消费者可以(或可能不)使用该查找值来确定要加入哪个其他表。
多表继承与您当前的架构更接近,所以我建议使用它,除非您需要将它与Linq to SQL或类似的ORM一起使用。
请参阅此处以获取详细的详细教程:Implementing Table Inheritance in SQL Server。
答案 1 :(得分:9)
查找人,车辆,构建, Office 的常见内容。由于缺乏更好的术语,我使用了实体。然后在 Entity 及其子类型之间实现超类型/子类型关系。请注意,EntityID
在所有子类型表中都是PK
和FK
。现在,您可以将项表链接到实体(所有者)。
在此模型中,一个项只能属于一个实体;一个实体可以拥有(拥有)许多项。
答案 2 :(得分:0)
你的链接表没问题。
您将遇到的麻烦是您需要在运行时生成动态sql。参数化的sql通常不允许FROM列表中的对象成为参数。
我想要避免这种情况,你可以稍微去规范化 - 比如通过创建一个表来保存id(假设id在其他表中是唯一的)和type_id表示哪个表是源,以及生成的描述 - 例如来自初始记录的名称值。
当修改基本信息时,您将触发创建此非规范化列表,并且可以将其用于通用查询 - 然后在运行时需要时使用动态查询。