我正在准备一个旧版 Microsoft SQL Server 数据库,以便我可以通过诸如实体框架之类的 ORM 进行交互,而我的问题围绕着处理我的一些共享通用类型的多对多关联的设置。具体来说,应该在主类型之间共享一个公共类型,还是每个主类型都有自己的链接表?
例如,这是我编写的一个简单示例,它显示了当前如何设置感兴趣的表:
请注意,有两种类型,Teachers
和Students
,两者都可以包含零个、一个或多个PhoneNumbers
。Teachers
和两个表Students
实际上共享一个关联表 ( PeoplePhoneNumbers
)。该字段FKID
是 aTeacherId
或 a StudentId
。
我认为应该设置的方式是这样的:
这样,Teachers
表和Students
表都获得了自己的 PhoneNumbers 表。
我的直觉告诉我第二种方法是正确的方法。这是真的?即使 PhoneNumbers 表包含多个字段怎么办?我的面向对象程序员的大脑告诉我,如果这些表之间的唯一区别是它们链接到哪个主表,那么拥有几个相同的表是错误的,每个表都包含十几个字段?例如:
在这里,我们有两个包含相同信息的表,但唯一的区别是一个表是地址,Teachers
而另一个表是Students
。这些对我来说是多余的,它们实际上应该是一个表——但是我失去了数据库约束它们的能力(对吗?),并且当我尝试将 ORM 应用于此时,也让我自己变得更加混乱。
这种类型的公共类型应该合并还是应该为每个主类型保持分离?
更新
下面的答案将我引向了以下解决方案,该解决方案基于数据库中的子类表。我最初的问题之一是我有一个在多个其他表之间共享的公用表,因为该实体类型对其他两个表都是通用的。处理这个问题的正确方法是对共享表进行子类化,并从本质上将它们从一个公共父级降级,并将公共数据类型链接到这个新的父级。这是一个示例(请记住,我的实际数据库与教师和学生无关,因此此示例是高度制造的,但概念是有效的):
由于Teachers
和Students
都需要,因此解决方案是为表PhoneNumbers
创建一个超类Party
、 和 FK 。另请注意,您仍然可以对仅与. 在此示例中,我还对它们进行了子类化和向下一层,并将它们从.PhoneNumbers
Party
Teachers
Students
Students
PartTimeStudents
Learners
这个解决方案非常令人满意的地方是我在 ORM 中实现它,例如实体框架。
查询很容易。我可以使用特定电话号码查询所有教师和学生:
var partiesWithPhoneNumber = from p in dbContext.Parties
where p.PhoneNumbers.Where(x => x.PhoneNumber1.Contains(phoneNumber)).Any()
select p;
进行类似的查询同样容易,但仅适用于仅属于教师的电话号码:
var teachersWithPhoneNumber = from t in dbContext.Teachers
where t.Party.PhoneNumbers.Where(x => x.PhoneNumber1.Contains(phoneNumber)).Any()
select t;