How to implement a one-to-many relationship with an “Is Current” requirement

北战南征 提交于 2020-01-15 15:31:14

问题


Designing a database, there's a relationship between two tables, Job and Document. One Job can have multiple Documents, but one (and only one) of these Documents needs to be flagged as IsCurrent. This is not always the most recent Document associated with that Job.

Structurally, I can see two ways of doing this.

The first is to add a DocumentId column to Job, and a JobId column to Document. This will work, but creates a circular reference: when imported into Entity Framework you end up with the peculiar situation that a Job has both a Document and a Documents collection. Likewise that Document has both a Job and a Jobs collection.

The second is to add an IsCurrent bit flag to the Document table. This will work, but leaves it logically possible for a Job to have multiple IsCurrent Documents, which is not allowed.

Questions:

1) Am I right in thinking there's no "third way" out of this dilemma?

2) Presuming not, which is better, and why? I favour the second solution as it seems much cleaner and we can enforce the single IsCurrent through the business logic. My colleague favours the former solution because it results in simpler C# code and object references - if we rename the foreign keys, it should avoid the confusion created by Job/Jobs.


回答1:


If your back-end is SQL Server, you can create a filtered index to ensure that each job has at most one current document:

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

That way, it's not just enforced at the business level but is also enforced inside the database.




回答2:


just for a third way (and for fun): consider using not a bit, but an int equals to max + 1 among the documents of the job.

then create a unique index on {job FK, said int}.

you can:

  • change current by updating the int,
  • get the current by searching the max and
  • prevent to have more than one current because of the unique index.
  • create a new non current document by using min - 1 for said int.

this is not the simplest to implement.




回答3:


Yes there is a third way out of this dilemma. You need a DBMS that supports SQL's CREATE ASSERTION (and supports it correctly, of course). With such a DBMS, you can declare any data rule that applies to your situation and your DBMS will enforce that rule for you.

Unfortunately, no such DBMS exists * in the SQL world *. Outside of the SQL world, there are such engines. ASSERTIONs being my hobbyhorse, I wrote one myself. If you're interested, a Google search should lead you to it quickly.



来源:https://stackoverflow.com/questions/30624962/how-to-implement-a-one-to-many-relationship-with-an-is-current-requirement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!