如何实现具有 "Is Current" 需求的一对多关系
How to implement a one-to-many relationship with an "Is Current" requirement
设计数据库,两个table之间存在关系,Job
和Document
。一个 Job
可以有多个 Documents
,但是其中一个(并且只有一个)Documents
需要标记为 IsCurrent
。这并不总是与 Job
关联的最新 Document
。
在结构上,我可以看到两种方法。
首先是在Job
中添加DocumentId
列,在Document
中添加JobId
列。这会起作用,但会创建一个循环引用:当导入 Entity Framework 时,您会遇到 Job
同时具有 Document
和 Documents
集合的特殊情况。同样,Document
有一个 Job
和一个 Jobs
集合。
二是在Document
table上加一个IsCurrent
位标志。这会起作用,但从逻辑上讲,一个作业可以有多个 IsCurrent
Documents
,这是不允许的。
问题:
1) 我认为没有 "third way" 摆脱这种困境是对的吗?
2) 假设不是,哪个更好,为什么?我赞成第二种解决方案,因为它看起来更简洁,而且我们可以通过业务逻辑强制执行单个 IsCurrent
。我的同事喜欢前一种解决方案,因为它会导致更简单的 C# 代码和对象引用 - 如果我们重命名外键,它应该避免 Job/Jobs
造成的混淆。
只是为了第三种方式(也是为了好玩):考虑在作业的文档中使用 not a bit,但 int 等于 max + 1。
然后在 {job FK, said int} 上创建一个唯一索引。
您可以:
- 通过更新 int 改变电流,
- 通过搜索最大值获取电流
- 防止因为唯一索引而出现多个当前。
- 使用 min - 1 为所述整数创建一个新的非当前文档。
这不是最简单的实现方式。
是的,还有第三种方法可以摆脱这种困境。您需要一个支持 SQL 的 CREATE ASSERTION 的 DBMS(当然 正确 支持它)。使用这样的 DBMS,您可以声明适用于您的情况的任何数据规则,您的 DBMS 将为您执行该规则。
不幸的是,在 SQL 世界 * 中 * 不存在这样的 DBMS。在 SQL 世界之外,还有这样的引擎。断言是我的木马,我自己写了一个。如果您有兴趣,Google 搜索应该会很快找到它。
如果你的后端是SQL服务器,你可以创建一个filtered index来确保每个job
最多有一个当前文档:
CREATE UNIQUE INDEX IX_Documents_Current
ON Documents (JobId) where IsCurrent=1
这样一来,它就不会只是在业务级别强制执行,而是在数据库内部强制执行。
设计数据库,两个table之间存在关系,Job
和Document
。一个 Job
可以有多个 Documents
,但是其中一个(并且只有一个)Documents
需要标记为 IsCurrent
。这并不总是与 Job
关联的最新 Document
。
在结构上,我可以看到两种方法。
首先是在Job
中添加DocumentId
列,在Document
中添加JobId
列。这会起作用,但会创建一个循环引用:当导入 Entity Framework 时,您会遇到 Job
同时具有 Document
和 Documents
集合的特殊情况。同样,Document
有一个 Job
和一个 Jobs
集合。
二是在Document
table上加一个IsCurrent
位标志。这会起作用,但从逻辑上讲,一个作业可以有多个 IsCurrent
Documents
,这是不允许的。
问题:
1) 我认为没有 "third way" 摆脱这种困境是对的吗?
2) 假设不是,哪个更好,为什么?我赞成第二种解决方案,因为它看起来更简洁,而且我们可以通过业务逻辑强制执行单个 IsCurrent
。我的同事喜欢前一种解决方案,因为它会导致更简单的 C# 代码和对象引用 - 如果我们重命名外键,它应该避免 Job/Jobs
造成的混淆。
只是为了第三种方式(也是为了好玩):考虑在作业的文档中使用 not a bit,但 int 等于 max + 1。
然后在 {job FK, said int} 上创建一个唯一索引。
您可以:
- 通过更新 int 改变电流,
- 通过搜索最大值获取电流
- 防止因为唯一索引而出现多个当前。
- 使用 min - 1 为所述整数创建一个新的非当前文档。
这不是最简单的实现方式。
是的,还有第三种方法可以摆脱这种困境。您需要一个支持 SQL 的 CREATE ASSERTION 的 DBMS(当然 正确 支持它)。使用这样的 DBMS,您可以声明适用于您的情况的任何数据规则,您的 DBMS 将为您执行该规则。
不幸的是,在 SQL 世界 * 中 * 不存在这样的 DBMS。在 SQL 世界之外,还有这样的引擎。断言是我的木马,我自己写了一个。如果您有兴趣,Google 搜索应该会很快找到它。
如果你的后端是SQL服务器,你可以创建一个filtered index来确保每个job
最多有一个当前文档:
CREATE UNIQUE INDEX IX_Documents_Current
ON Documents (JobId) where IsCurrent=1
这样一来,它就不会只是在业务级别强制执行,而是在数据库内部强制执行。