Entity Framework Code First - 循环关系的奇怪行为

Entity Framework Code First - strange behaviour with circular relationship

我很难理解 Code First 如何基于模型建立关系。这是模型:

public class Person
{
    [Key]
    public string PersonName { get; set; }

    [Required]
    public virtual Nation NationOfBirth { get; set; }

    [Required]
    public virtual Nation CurrentNationOfResidence { get; set; }
}

public class Nation
{
    [Key]
    public string NationName { get; set; }

    public virtual Person CurrentSecondInCommand { get; set; }
}

起初我在创建数据库时遇到错误,我通过添加几个 modelBuilder 命令解决了这个问题:

modelBuilder.Entity<Person>()
    .HasRequired(p => p.NationOfBirth)
    .WithRequiredDependent()
    .WillCascadeOnDelete(false);
modelBuilder.Entity<Person>()
    .HasRequired(p => p.CurrentNationOfResidence)
    .WithRequiredDependent()
    .WillCascadeOnDelete(false);

我还补充了:

modelBuilder.Entity<Nation>()
    .HasOptional(n => n.CurrentSecondInCommand)
    .WithOptionalDependent()
    .WillCascadeOnDelete(false);

现在,当我尝试使用以下代码填充我的数据库时:

var america = new Nation { NationName = "America" };
context.Nations.Add(america);
var bush = new Person { PersonName = "Bush", CurrentNationOfResidence = america, NationOfBirth = america };
var obama = new Person { PersonName = "Obama", CurrentNationOfResidence = america, NationOfBirth = america };
var biden = new Person { PersonName = "Biden", CurrentNationOfResidence = america, NationOfBirth = america };
context.People.Add(bush);
context.People.Add(obama);
context.People.Add(biden);
context.SaveChanges();

在添加 'bush' 的位置,CurrentNationOfResidence 和 NationOfBirth 属性对他来说都不为空,并且设置为 'america' 对象。但是一旦添加 'obama','bush' 上的 CurrentNationOfResidence 和 NationOfBirth 属性都会变为空。添加 'biden' 后 'obama' 也会发生同样的情况。

如果我检查由此生成的数据库,我看不到在 People table 上创建的任何外键列,但我希望 Code First 自动生成 2 个外键Person 上的两个 Nation 字段(这就是我认为我的前两个 modelBuilder 命令会做的 - 来自 "WithRequiredDepedent" 的描述)。更奇怪的是,数据库中添加了一个名为 "America" 的人,以及一个也称为 America 的国家。

如果有人能提供有关我的模型的一般建议,我将不胜感激。我意识到我在这里有一个循环关系,但我认为这没关系,因为国家不需要有 CurrentSecondInCommand。我意识到它有点复杂(或者也许用令人费解的词更好)但我认为它是有道理的:

非常欢迎任何建议,谢谢。

国家 class 中的虚拟 属性 必须是 ICollection<Person> CurrentSecondInCommand,这样你在数据库中就会有 "many persons in one nation" 关系将是 "one to many" 而不是"one to one"

Person与Nation的两种关系不是一对一的,而是多对一的:

  • 一个人必须有一个(民族)出生国。但是一个国家有很多人在那里出生
  • 一个人必须有一个(国家)CurrentNationOfResidence。但是一个国家有很多居民

所以你的配置应该是:

modelBuilder.Entity<Person>()
    .HasRequired(p => p.NationOfBirth)
    .WithMany()
    .WillCascadeOnDelete(false);
modelBuilder.Entity<Person>()
    .HasRequired(p => p.CurrentNationOfResidence)
    .WithMany()
    .WillCascadeOnDelete(false);