【问题标题】:How to implement a one-to-many relationship with an "Is Current" requirement如何实现具有“当前”要求的一对多关系
【发布时间】:2015-08-17 22:48:34
【问题描述】:

在设计数据库时,两个表之间存在关系,JobDocument。一个Job 可以有多个Documents,但其中一个(并且只有一个)Documents 需要标记为IsCurrent。这并不总是与该Job 关联的最新Document

在结构上,我可以看到两种方法。

首先是在Job 中添加DocumentId 列,在Document 中添加JobId 列。这会起作用,但会创建一个循环引用:当导入实体框架时,您最终会遇到Job 同时具有DocumentDocuments 集合的特殊情况。同样,Document 有一个 Job 和一个 Jobs 集合。

第二种是在Document 表中添加一个IsCurrent 位标志。这会起作用,但逻辑​​上一个 Job 可以有多个 IsCurrent Documents,这是不允许的。

问题:

1) 我是否认为没有“第三条路”可以摆脱这种困境?

2) 假设不是,哪个更好,为什么?我赞成第二种解决方案,因为它看起来更干净,我们可以通过业务逻辑强制执行单个 IsCurrent。我的同事喜欢前一种解决方案,因为它会导致更简单的 C# 代码和对象引用 - 如果我们重命名外键,它应该避免 Job/Jobs 造成的混淆。

【问题讨论】:

    标签: sql database entity-framework database-design relational-database


    【解决方案1】:

    如果你的后端是SQL Server,你可以创建一个filtered index来保证每个job最多有一个当前文档:

    CREATE UNIQUE INDEX IX_Documents_Current
        ON Documents (JobId) where IsCurrent=1
    

    这样,它不仅只是在业务级别强制执行,而且还在数据库内部强制执行。

    【讨论】:

    • 太好了,谢谢。我认为过滤索引是性能工具——我不知道它们可以用来加强完整性。
    • @MattThrower - 如果您考虑一下,任何唯一索引至少在某些方面具有强制完整性。
    • 如此简单,如此优雅......精彩等等:总是阅读所有一次性工具的文档。
    【解决方案2】:

    只是为了第三种方式(并且是为了好玩):考虑在作业的文档中使用一个等于 max + 1 的 int 而不是位。

    然后在{job FK,表示int}上创建一个唯一索引。

    你可以:

    • 通过更新 int 来改变电流,
    • 通过搜索最大值和获取当前
    • 由于唯一索引,防止拥有多个当前。
    • 对所述 int 使用 min - 1 创建一个新的非当前文档。

    这不是最容易实现的。

    【讨论】:

      【解决方案3】:

      是的,还有第三种方法可以摆脱这种困境。您需要一个支持 SQL 的 CREATE ASSERTION 的 DBMS(当然,正确支持它)。使用这样的 DBMS,您可以声明适用于您的情况的任何数据规则,并且您的 DBMS 将为您强制执行该规则。

      很遗憾,* 在 SQL 世界中* 中不存在这样的 DBMS。在 SQL 世界之外,还有这样的引擎。断言是我的爱好,我自己写了一个。如果您有兴趣,可以通过 Google 搜索快速找到它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-22
        • 1970-01-01
        • 2012-11-25
        • 2020-01-26
        相关资源
        最近更新 更多