2017-09-10 34 views
0

例如。在我的系统中,我有一个对象被其他几种类型的对象以1对1的关系使用。让我们调用使用Address的对象,以及使用它的两个对象Company和Person。每个公司和个人都有一个地址,每个地址在系统中都是唯一的,因此每个地址都由个人或公司引用。1对1与超过2个表的关系

我有两个问题。

问题1)这个关系叫什么?我在网上找到的1对1关系的所有例子都只在两个表之间,而这是三对一的关系。

问题2)什么样的表结构最好地捕获了这种关系?我发现至少有两种看起来有缺陷的潜在设计。

设计a)使用两个可为空的外键,约束条件是至少有一个不为空。就像一个复合外键。

- Company - 
pkCompanyId 
... 

- Person - 
pkPersonId 
... 

- Address - 
pkAddressId 
fkPersonId <nullable> 
fkCompanyId <nullable> 
... 

设计b)每个公司和个人识别它使用的地址。

- Company - 
pkCompanyId 
fkAddressId 
... 

- Person - 
pkPersonId 
fkAddressId 
... 

- Address - 
pkAddressId 
... 

设计一)似乎是一个更传统的使用外键我在正在使用的对象标识引用它的对象,但我还没有看到任何的例子是与做多这样的外键。

设计b)看起来像是正常建模1对1关系的反过程。

在我看来,在常规的1对1关系(下面)中,fkPersonId是一个不可为空的唯一外键有助于在实际表结构中强制执行1对1关系(它保证每个地址被一个没有引用其他地址的Person引用)。我的设计都没有达到这个目标。在设计中a)必须确保fkCompanyId或fkPersonId中的一个且仅有一个为空以确保一致性。在设计b)中,必须确保公司或人员中的任何fkAddressId都不在任何表中重复。这使我怀疑我在这里犯了一个错误。

- Person - 
pkPersonId 
... 

- Address - 
pkAddressId 
fkPersonId 
... 

没有太多的精力,我可以看到其他的设计,例如使用guid作为pkCompanyId和pkPersonId以及Address中的单个外键,但我再次在我所研究的任何在线资源中看不到任何此策略的示例。

我已经明显超出了我对数据库设计的有限知识,可以使用一些指导。处理这个问题的最好方法是什么?

更新响应沃尔特米蒂的回答

我认为单个表继承不适合我的情况。尽管我在这里使用了公司和人员的例子,但在我的真实应用程序中,这些都是大型复杂表格,除了它们都拥有地址之外,没有任何共同之处。他们的数据不仅非常不同,而且代表完全不同的概念。

我的每个具有相同类型实例的实际实体都是Organization,Project和ProjectElement。组织代表许可使用系统的公司。项目表示由特定组织的用户创建的项目,ProjectElement表示一段项目数据。

他们都有一个实例的东西是一个设置对象。默认设置在组织级别提供。创建项目时,会获取组织设置的副本。项目中的组件获得项目设置的副本。

此体系结构支持多种用例,包括何时修改组织的设置时,这些更改仅影响新项目,而不影响已创建的项目。 ProjectElement继承了Project的设置,但可以选择覆盖特定的Project设置。

更进一步的复杂性包括组织,项目和ProjectElement不仅仅具有一个共享类型的实例,而是几个。有几种不同类型的设置对象,每个都有自己的表格。如果不能使用共享类型的实例的ID作为引用对象的主键,则这使得它变得尴尬。我也在使用目前不支持视图的实体框架核心ORM。

你的答案非常有用,给了我很多思考,但到目前为止,似乎我的设计2最好的实现了我的要求。设计2有什么内在不合理的地方让它不适合?

+0

当然。我的建议是基于你最初提出的简单案例。 –

回答

1

你的问题看起来像一个类型和子类型(或类和子类)的情况。在我尝试处理你的两个问题之前,我将尝试重新构建它,然而,作为两个关系。

首先,我要发明一个新的实体,我将其称为“联系人”。系统中的每个地址都由联系人引用,每个联系人都有一个或多个地址。

每个联系人都是一个人或一个公司,但不是两个。

现在,至少在概念上,我们首先将地址与联系人连接,然后将该联系人与个人或公司联系起来。在逻辑和物理层面上,这可能是矫枉过正的。也就是说,它可能会增加复杂性而不增加价值。我无法强调这一点。

但概念清晰度对其本身是有价值的。

现在对你的问题1.

联系人和地址之间的关系仅仅是一个典型的“有-A”式的关系,就像很多你以前见过。

但是,联系人与个人或公司之间的关系是一种不同的关系,您可能以前从未见过。它被称为各种名称,这是我对您的问题的答案1.

它有时被称为正是“IS-A关系”。在ER建模中,它通常被称为“专业化/泛化”关系。在对象建模中,虽然常常使用流行语“派生类”或“扩展类”,但它通常被称为“类/子类关系”。它也与继承的对象概念有关。

然而,关于对象建模的警告一句话。如果您打算在同一个项目中进行对象建模和数据建模,那么最好对它们有更深入的了解,以及它们是如何为您的项目增加价值的。否则,你很可能陷入这样的陷阱:认为一个模型或另一个模型简直是无法理解或无用。比我更聪明的人多次陷入这个陷阱。

现在是第二个问题。有两种方法可以为这种情况设计表格。一个称为“单表继承”,另一个称为“类表继承”。我把连字符放进去的原因是这两个主题在这个区域有标签,并且查看这两个标签下的问题和信息可能会对您有所帮助。

单表继承。

我们将有两个表格,一个用于地址,另一个用于联系人。

地址:

AddressID (PK) 
ContactID (FK references Contact) 
Street Address 
City, 
State, 
Zipcode, 
etc. 

联系人:

ContactID (PK) 
ContactType (Person or Company, coded) 
First Name 
Last Name, 
Company Name, 
etc. 

公司名称将是人的情况下,NULL,姓氏,名字将在公司的情况下,NULL)。

类表继承

我们将有四个表,地址,联系方式,个人和公司

地址:

AddressID (PK) 
ContactID (FK references Contact) 
Street Address 
City, 
State, 
Zipcode, 
etc. 

联系人:

ContactID (PK) 

人:

ContactID (PK, and FK references Contact) 
First Namme, 
Last Name, 
etc. 

公司:

ContactID (PK and FK references Contact) 
Company Name 
etc. 

对于你的情况,我建议单表继承。但是对于非常复杂的IS-A关系来说,类表继承可以更好地工作。

+0

已在我的操作系统更新中回复。 – Neutrino