设计只能拥有2个外键中的一个的数据库实体?

时间:2013-01-12 08:05:14

标签: .net database hibernate nhibernate database-design

我们系统中的进程负责根据特定规则发送文件。根据文件名,可以将文件发送给客户或工厂(但不能同时发送)。

规则的每一行都包含文件名过滤器,它所属的客户和工厂,并指定其他参数,例如目标文件夹,文件是否需要加密,拆分,组合,重命名等。 / p>

在此过程中,我们将了解文件所属的工厂和客户,我们将查看工厂和客户的规则,并应用与过滤器匹配的文件的规则(优先级将给予客户规则)

表示规则与数据库中客户/工厂之间关系的最佳方式是什么?我们已经在数据库中有Customer和Factory表,但我想不出表示关系的最佳方式。每条规则都只有一个FK(客户或工厂,它不能同时拥有两个,也不能没有)。表示这一点的方法之一就是:

enter image description here

但这并不能说明它只能拥有两个FK中的一个。我们可以设置一个约束,其中一个需要有效FK而另一个必须是空的,但它似乎不是很干净。此外,如果我们有其他规则的决定因素(例如国家),它将变得更加丑陋。知道如何改进这种设计吗?

我认为这也有助于指定系统是用.NET开发的,我们使用对象关系映射,即NHibernate。

4 个答案:

答案 0 :(得分:6)

看看table inheritance

您可以使用以下内容:

Rule
  int RuleId
  int TypeRule
  PK (RuleId)
  UQ (RuleId, TypeRule)

CustomerRule
  int TypeRule = 1
  int CustomerId
  FK (TypeRule, RuleId)
  FK CustomerId

FactoryRule
  int TypeRule = 2
  int FactoryId
  FK (TypeRule, RuleId)
  FK FactoryId

使用这样的系统,您有客户规则或工厂规则,而不是两者。另外,明天添加CountryRule很容易。

答案 1 :(得分:3)

使用Hibernate及其Table-per-Subclass Mapping Strategy,您可以定义一个抽象的Rule-Class,将它专门用于Customers和Factories,并将类层次结构映射到关系数据库模式,如下所示:

Mapping

答案 2 :(得分:1)

如何引入新实体而不是2 FK?它将有3个字段,即它自己的PK和两个FK。你可以介绍一些自定义逻辑,让其中一个FK为空。逻辑上更清楚的是,您只有一个FK用于该任务,并且相应的实体负责处理细节。

答案 3 :(得分:1)

我知道你提到你不想对此使用约束这一事实,但是阅读任何答案以及它们指向表继承的方向这一事实我想告诉我一些个人经历。

数据库并不是要复制面向对象的原则,我不确定NHibernate,但实体框架非常严格,一旦你实现了这个继承,你可能会遇到这样一个事实:你要继承几个类型,这是不可能的(在EF这是一个事实)。我的意思是你有一个规则可以定义为客户规则和工厂规则(或者系统将来可能知道的任何其他类型的规则)。

我已经完成了表继承和约束的实现,后者为我提供了最灵活的模型,我对这个解决方案仍然非常满意。你用最少的努力思考最简单的方法是件好事,但有时候复杂的问题需要的是一个非常简单的解决方案。