实体框架代码优先 - 循环关系的奇怪行为

时间:2016-02-08 12:16:26

标签: c# .net entity-framework ef-code-first

我很难理解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.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();

在&#39; bush&#39;添加后,CurrentNationOfResidence和NationOfBirth属性对他来说都不为空,并且被设置为“美国”&#39;宾语。但是,只要&#39;奥巴马&#39;添加了,&#39; bush&#39;上的CurrentNationOfResidence和NationOfBirth属性。两者都变为空。 “奥巴马”也是如此。曾经&#39; biden&#39;已添加。

如果我检查由此生成的数据库,我看不到在People表上创建的任何外键列,但我希望Code First能够为两个Nation字段自动生成2个外键on Person(我认为我的前两个模型构建器命令会做什么 - 来自&#34的描述; WithRequiredDepedent&#34;)。甚至更奇怪的是,有一个名为&#34; America&#34;已被添加到数据库中,以及一个也被称为美国的国家。

如果有人能提供,我真的很感激我的模型上的一些建议。我意识到我在这里有一个循环关系,但我认为这样可以,因为国家不需要有一个CurrentSecondInCommand。我意识到它有点复杂(或者可能是一个更好的词),但我认为这是有道理的:

  • 一个人必须有一个(国家)NationOfBirth。
  • 一个人必须有一个(国家)CurrentNationOfResidence。
  • Nation可以选择使用单个(Person)CurrentSecondInCommand。

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

2 个答案:

答案 0 :(得分:1)

从人到国家的两个关系不是一对一的,而是多对一的:

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

所以你的配置应该是:

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

答案 1 :(得分:0)

Nation类中的虚拟属性必须是ICollection<Person> CurrentSecondInCommand,这样你在数据库中将拥有“一个国家中的许多人”这种关系将是“一对多”而不是“一对一”