设计数据库时,两个表Job
和Document
之间存在关系。一个Job
可以有多个Documents
,但这些Documents
中只有一个(只有一个)需要标记为IsCurrent
。这并不总是与Document
相关联的最新Job
。
在结构上,我可以看到两种方法。
第一个是向DocumentId
添加Job
列,向JobId
添加Document
列。这将起作用,但会创建一个循环引用:当导入到Entity Framework时,最终会出现Job
同时拥有Document
和Documents
集合的特殊情况。同样地,Document
同时包含Job
和Jobs
集合。
第二种是向IsCurrent
表添加Document
位标志。这可行,但在逻辑上可以让作业有多个IsCurrent
Documents
,这是不允许的。
问题:
1)我是否正确地认为没有"第三种方式"摆脱这种困境?
2)假设没有,哪个更好,为什么?我赞成第二种解决方案,因为它似乎更清晰,我们可以通过业务逻辑强制执行单IsCurrent
。我的同事赞成以前的解决方案,因为它导致更简单的C#代码和对象引用 - 如果我们重命名外键,它应该避免由Job/Jobs
创建的混淆。
答案 0 :(得分:3)
如果您的后端是SQL Server,则可以创建filtered index以确保每个job
最多包含一个当前文档:
CREATE UNIQUE INDEX IX_Documents_Current
ON Documents (JobId) where IsCurrent=1
这样,它不是仅在业务级别强制执行,而是在数据库中强制执行。
答案 1 :(得分:1)
只是为了第三种方式(并且为了好玩):考虑使用不多,但是int等于作业文档中的max + 1。
然后在{job FK,表示int}上创建一个唯一索引。
你可以:这不是最简单的实施方式。
答案 2 :(得分:1)
是的,还有第三种方法摆脱了这种困境。您需要一个支持SQL的CREATE ASSERTION的DBMS(并且当然支持正确)。使用这样的DBMS,您可以声明适用于您的情况的任何数据规则,并且您的DBMS将为您强制执行该规则。
不幸的是,在SQL世界* 中没有这样的DBMS *。在SQL世界之外,有这样的引擎。 ASSERTIONs是我的木马,我自己写了一个。如果您有兴趣,Google搜索会引导您快速浏览。