【问题标题】:Designing database entity that can only have exactly one of 2 foreign key?设计只能具有两个外键之一的数据库实体?
【发布时间】:2013-01-12 08:05:14
【问题描述】:

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

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

在这个过程中,我们会知道一个文件所属的工厂和客户,我们会查看工厂和客户的规则并对匹配过滤器的文件应用规则(将优先考虑客户规则)

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

但这并没有捕捉到它只能具有两个 FK 之一的事实。我们可以设置一个约束,其中一个必须是有效的 FK,另一个必须为空,但它似乎不是很干净。此外,如果我们有其他规则决定因素(例如国家),它会变得更丑陋。知道如何改进这个设计吗?

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

【问题讨论】:

  • 如果客户和工厂之间有一些共享数据,显而易见的是引入一个客户和工厂都派生的基类。然后 FK 将转到基类

标签: .net database hibernate nhibernate database-design


【解决方案1】:

看看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 很容易。

【讨论】:

  • 这是 SQL 服务器功能吗?知道它是如何与 NHibernate 一起工作的吗?
【解决方案2】:

使用 Hibernate 及其Table-per-Subclass Mapping Strategy,您可以定义一个抽象的规则类,将其专门用于客户和工厂,并将类层次结构映射到关系数据库架构,如下所示:

【讨论】:

    【解决方案3】:

    引入一个新实体而不是 2 个 FK 怎么样?它将有3个字段,即自己的PK和两个FK。比您可以引入一些自定义逻辑来使其中一个 FK 为空。从逻辑上讲,您只有一个 FK 来完成该任务,并且各个实体负责处理细节。

    【讨论】:

      【解决方案4】:

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

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

      我已经完成了表继承和约束的实现,后者最终为我提供了最灵活的模型,我对这个解决方案仍然很满意。您正在考虑以最少的努力实现最简单的方法,这很好,但有时复杂的问题需要不那么简单的解决方案只是一个事实。

      【讨论】:

        猜你喜欢
        • 2018-11-22
        • 2019-04-16
        • 2023-03-19
        • 2018-07-06
        • 1970-01-01
        • 2012-06-06
        • 2021-10-26
        • 2010-12-24
        • 1970-01-01
        相关资源
        最近更新 更多