所以我有这个课程:
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; }
}
使用代码优先的实体框架,一切似乎都得到了设置,正如我所期望的那样。我在Question
和Answer
之间存在一对多关系,删除Question
会导致关联的Answer
消失(我认为)。
现在我想将其添加到Question
类:
public virtual Answer RightAnswer { get; set; }
我想在Question
和Answer
之间建立一对一的关系(除了Answers
和Question
之间的一对多关系之外这是问题开始的地方。问题发生是因为级联删除。数据库现在看到它的方式,删除问题会删除答案(包括RightAnswer
),这会导致它再次尝试删除Question
(或者它可能会删除Answer
1}}删除Question
,然后删除Answer
,无论哪种方式)。要解决这个问题,我需要告诉它 not 级联删除该一对一关系。而且,不幸的是,要做到这一点,我必须深入研究流体API,在这里我不确定正确的方法。
我有这个:
modelBuilder.Entity<Question>()
.HasRequired(p => p.RightAnswer)
.WithRequiredDependent()
.WillCascadeOnDelete(false);
但我真的不确定这应该是WithRequiredDependant
还是WithRequiredPrinciple
。或者在这种情况下甚至是重要的。
(是的,我知道另一个解决方案就是将IsRight
bool添加到Answer
,但现在我想弄清楚我是否可以这样做而不是这样做了)
答案 0 :(得分:3)
尽管应尽可能避免关系数据库表之间的循环关系,但我可能会认真考虑“其他方法”。
按EF条款,关系的 principal 是被引用的表,依赖是引用主要PK到FK的表。
对于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);
请注意,最后两个流畅的API调用是可选的,可以跳过。 Map
用于指定与本例RightAnswer_AnswerId
中的常规名称不同的FK列名称。并且可以跳过WillCascadeOnDelete(false)
,因为按照惯例,可选关系会关闭级联删除。但是明确不会受到伤害,特别是在播放/修改模型时。
答案 1 :(得分:0)
One-to-zero/one Relationship
:
modelBuilder.Entity<Question>()
.HasOptional(q => q.RightAnswer)
.WithRequired(q => q.Question)
.WillCascadeOnDelete(false);
One-to-one Relationship
:
modelBuilder.Entity<Question>()
.HasRequired(q => q.RightAnswer)
.WithRequiredPrincipal(q => q.Question)
.WillCascadeOnDelete(false);