How to solve combined one-to-one and one-to-many relationship in EF 5 Code First

巧了我就是萌 提交于 2019-12-03 20:51:53
Slauma

For both your questions Q1 and Q2 you will need two roundtrips/two calls to SaveChanges (aside from solving the problem with a Stored Procedure maybe).

Q1: The first call having Question.CorrectAnswer set to null and a second call that sets the CorrectAnswer to one of the stored answers.

Q2: The first call setting Question.CorrectAnswer to null and the second call deletes the Question and the related answers with enabled cascading delete.

If you are not so worried about the two roundtrips but more about the two transactions corresponding to the two SaveChanges calls you can wrap the whole operation including the two SaveChanges calls into a single manual transaction. (Example: EF: How do I call SaveChanges twice inside a transaction?)

About the one-to-one relationship: Although from business perspective the relationship for the CorrectAnswer is one-to-one it is hard or even impossible to model it as a one-to-one relationship with EF.

The problem is that EF does not support foreign key one-to-one associations, i.e. relationships where the foreign key (CorrectAnswerId or so) has a unique constraint. It only supports shared primary key one-to-one associations where the primary key of the dependent (Question) is the foreign key (for Question.CorrectAnswer) to the principal (Answer) at the same time. Your Fluent code is the configuration for such a shared primary key association. But it would mean that the only valid CorrectAnswer is the Answer that has the same primary key value as the Question. While this is theoretically possible to achieve (your Answer table has more records than the Question table) it would most likely require to not use autogenerated keys but supply the keys manually. Changing the CorrectAnswers from one Answer to the other would be impossible. So, shared primary keys are not suited for your model in my opinion.

The better solution would be to remove your Fluent mapping. The result would be a one-to-many relationship with a nullable foreign key for CorrectAnswer in the Question table. From database perspective it means that the same Answer can be the CorrectAnswer for many Questions which is probably nonsense in your business logic because every question has its own unique set of answers and two questions never share the same answer. But you can "hide" this one-to-many relationship from your business logic by just not adding an inverse collection property (like QuestionsThisIsTheCorrectAnswerFor) to Answer. Although it does not model the business constraint perfectly it works technically without problems.

More about the difficulties of one-to-one relationships with EF can be found in these blog posts:

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