c# - Fluent API、一对一关系和级联删除

标签 c# entity-framework

所以我有这个类:

public class Question
{
    public int QuestionId { get; set; }
    public string QuestionText { get; set; }
    public bool IsInactive { get; set; }

    public virtual ICollection<Answer> Answers { get; set; }
}

还有这个:

public class Answer
{
    public Guid AnswerId { get; set; }
    public string AnswerText { get; set; }

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

并且使用代码优先的 Entity Framework ,一切似乎都按照我的预期进行了设置。我在 QuestionAnswer 之间有一个一对多的关系,删除一个 Question 会导致关联的 Answer消失(我认为)。

现在我想将它添加到 Question 类中:

public virtual Answer RightAnswer { get; set; }

我想在 QuestionAnswer 之间建立一对一的关系(除了 Answers< 的一对多关系Question 属性),这就是问题开始的地方。问题是由于级联删除而发生的。数据库现在看到它的方式是,删除问题会删除答案(包括 RightAnswer),这会导致它再次尝试删除 Question(或者它可能正在删除Answer 会删除 Question,后者随后会删除 Answer,无论哪种方式)。为了解决这个问题,我需要告诉它不要为一对一关系级联删除。而且,不幸的是,要做到这一点,我必须深入研究流畅的 API,在这里我不确定正确的方法。

我有这个:

modelBuilder.Entity<Question>()
    .HasRequired(p => p.RightAnswer)
    .WithRequiredDependent()
    .WillCascadeOnDelete(false);

但我真的不确定这应该是 WithRequiredDependant 还是 WithRequiredPrinciple。或者在这种情况下是否重要。

(是的,我知道另一种解决方案是向 Answer 添加一个 IsRight bool 值,但现在我想知道我是否可以这样做方式代替)

最佳答案

这是可能的,虽然应该尽可能避免关系数据库表之间的循环关系,所以我会认真考虑“其他方法”。

根据 EF 术语,关系的主体 是被引用的表,从属 是通过 FK 引用主体 PK 的表。

对于 RightAnswer定义关系,Question将引用 Answer通过 FK,因此 Answer是校长和Question是依赖者。

因此从这个角度来看,您的流畅配置是正确的(Dependent 中的词 WithRequiredDependent 适用于正在配置的实体,在您的情况下是 Question - 来自 Entity<Question> )。

然而,与其他一对多关系的组合则不然。为什么?因为循环依赖。 Answer需要 QuestionId FK,所以如果不先创建 Question 就无法创建它.通过制作 RightAnswer需要 Question必须先创建 Question 才能创建.这就造成了无法解决的先有鸡还是先有蛋的问题。

因此 RightQuestion应该是可选的。这导致了另一个问题。如果我们制作 Answer需要,EF 按照惯例会将其视为主体,这不是我们想要的。

所以这种模型唯一可行的解​​决方案是让两端都可选:

modelBuilder.Entity<Question>()
    .HasOptional(p => p.RightAnswer)
    .WithOptionalDependent()
    .Map(m => m.MapKey("RightAnswerId"))
    .WillCascadeOnDelete(false);

请注意,最后两个 Fluent API 调用是可选的,可以跳过。 Map在这种情况下用于指定与常规不同的 FK 列名称 RightAnswer_AnswerId .和 WillCascadeOnDelete(false)可以跳过,因为按照惯例,级联删除对于可选 关系是关闭的。但明确不会造成伤害,尤其是在播放/修改模型时。

关于c# - Fluent API、一对一关系和级联删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48214217/

相关文章:

c# - ASP.NET MVC 4 捆绑 - Debug模式下的单个文件 URL

c# - 在 Entity Framework 5 C# 中添加记录

c# - 按 Entity Framework 中的子表排序

c# - 如何使 ServiceStack 与现有的 MVC/Service/Repository 模式一起工作

sql - 在 Entity Framework 中的两个模型的实体之间加入

c# - 使用 Web API 过滤

c# - 过滤强类型结果

c# - 使用类型化的 HttpClient 创建 LinkedTokenSource

c# - XDocument 获取所有具有属性的节点

c# - 为什么 Bitmap.FromFile() 返回 Image 类型的对象