如何解决合并一个一对一和一对许多EF 5码首先关系(How to solve combined on

2019-08-16 19:25发布

I'm使用实体框架5和代码第一次。

我有两个域的实体问题答案测验应用。 一个问题有几个可能的答案。 一个问题也有,应引用可能答案的一个一个正确答案。 我遇到与之间的实体一个一对多和一对一的一对一关系的组合的一些问题。 见Q1Q2。

这是实体的代码:

public class Question
{
    public virtual int Id { get; set; }
    [Required]
    public virtual string Text { get; set; }

    [InverseProperty("Question")] 
    public virtual ICollection<Answer> PossibleAnswers { get; set; }
    public virtual Answer CorrectAnswer { get; set; }        

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public virtual DateTime? UpdateStamp { get; set; }
}

public class Answer
{
    public virtual int Id { get; set; }
    [Required]
    public virtual string Text { get; set; }

    [ForeignKey("QuestionId")]
    public virtual Question Question { get; set; }
    public virtual int QuestionId { get; set; }
}

Q1:我应该怎么做才能够在短短一个往返问题的目标和参考答案(直通财产PossibleAnswers)插入到数据库(例如,一个调用的SaveChanges环境)? 我得到当我保存的问题和答案不添加答案首先是错误:

无法确定相关的操作有效的排序。 依赖性可以存在由于外键约束,模型的要求,或存储生成的值。

为了解决这个问题,我试过用流利的API只需一个电话的objectcontexts的SaveChanges时做这一切,以获得问题的答案之前加入以下内容:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Question>()
            .HasOptional(q => q.CorrectAnswer)
            .WithRequired();

        base.OnModelCreating(modelBuilder);
    }

然而,这导致我到另一个错误:

检测到冲突的更改。 试图插入多个实体使用相同的密钥时,可能发生这种情况。

我是与Q1流畅API的方式在正确的道路上? 为什么错误信息?

Q2:当删除我知道会有一个错误,因为这个问题不能解答之前被删除,反之亦然的问题。 我该如何解决这个问题? 例如,被WillCascadeOnDelete应该是两个Question.CorrectAnswer和Question.PossibleAnswers规定?

Answer 1:

对于这两个问题的Q1和Q2,你将需要两个往返/两次调用SaveChanges (除了解决与存储过程中的问题,也许)。

Q1:第一呼叫具有Question.CorrectAnswer设置为null ,并且设置一个第二呼叫CorrectAnswer所存储的答案中的一个。

Q2:第一次调用设置Question.CorrectAnswernull的第二呼叫删除Question ,并启用级联删除相关的答案。

如果你不是那么担心两个往返,但更多的对应于两个两个交易SaveChanges调用你可以用整个操作包括两个SaveChanges调用到一个单一的手动事务。 (例如: EF:我如何调用的SaveChanges两次事务中? )

关于一个一对一的关系:虽然从商业的角度来看的关系CorrectAnswer是一个对一个很难甚至不可能将其建模与EF一比一的关系。

问题是,EF不支持外键一个-to-one关联,即关系,其中外键(CorrectAnswerId左右)具有独特的约束。 它仅支持共享主密钥一个一对一的关联,其中从属(的主键Question )是外键(对于Question.CorrectAnswer )到主体( Answer同时)。 您的流利代码为这样的共享主键相关联的配置。 但是,那岂不是唯一有效的CorrectAnswerAnswer具有相同的主键值的Question 。 虽然这在理论上是可能实现(你的Answer表比更多的记录Question表),这很可能会要求不使用自动生成的密钥,但手动提供的钥匙。 更改CorrectAnswers从一个Answer到另一个是不可能的。 因此,共享主键不适合在我看来,你的模型。

更好的解决办法是删除你的流利的映射。 其结果将是一个空的外键的一到多的关系CorrectAnswerQuestion表。 从数据库的角度来看这意味着同样的Answer可以是CorrectAnswer许多Question S的可能是在你的业务逻辑的废话,因为每一个问题都有其自己的一套独特的答案和两个问题不共用相同的答案。 但是你可以“隐藏”从你的业务逻辑通过只是不加逆集合属性(像这样的一对多关系QuestionsThisIsTheCorrectAnswerFor )来Answer 。 虽然它没有商业约束模型完美它工作在技术上没有问题。

更多关于EF一个一对一关系的困难可以在这些博客文章中找到:

  • 共享主键一to-one关联
  • 一到一个外键关联


文章来源: How to solve combined one-to-one and one-to-many relationship in EF 5 Code First