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

C# 实体框架代码优先-具有循环关系的奇怪行为,c#,.net,entity-framework,ef-code-first,C#,.net,Entity Framework,Ef 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 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);
在添加“bush”时,CurrentNationFresidence和NationOfBirth属性对他来说都不是空的,并且被设置为“america”对象。但一旦添加了“奥巴马”,则“布什”上当前的NationFresidence和NationOfBirth属性都将变为空。一旦“拜登”被加入,同样的情况也会发生在“奥巴马”身上

如果我检查由此生成的数据库,我看不到在People表上创建的任何外键列,但我希望代码首先为Person上的两个Nation字段自动生成2个外键(我认为我的前两个modelBuilder命令会这样做-根据更奇怪的是,有一个叫“美国”的人被添加到数据库中,还有一个国家也被称为美国

如果有人能提供一些关于我的模型的建议,我真的很感激。我意识到我在这里有一个循环关系,但我认为这是可以的,因为国家不需要有第二个指令。我意识到这有点复杂(或者说“迂回”是一个更好的词),但我认为这是有意义的:

  • 一个人必须有一个单一的(国家)出生
  • 一个人必须有一个单一(国家)的国家认同感
  • 一个国家可以选择有一个(个人)CurrentSecond命令

非常欢迎您提供任何建议,谢谢。

国家级虚拟财产必须是
ICollection CurrentSecondInCommand
,这样您的数据库中将有“一个国家中的多个人”。关系将是“一对多”而不是“一对一”“

人与国家之间的两种关系不是一对一,而是多对一:

  • 一个人必须有一个单一的(国家)出生。但是一个国家有许多人出生在那里
  • 一个人必须有一个单一(国家)的国家认同感。但是一个国家有很多居民
因此,您的配置应该是:

modelBuilder.Entity<Person>()
    .HasRequired(p => p.NationOfBirth)
    .WithMany()
    .WillCascadeOnDelete(false);
modelBuilder.Entity<Person>()
    .HasRequired(p => p.CurrentNationOfResidence)
    .WithMany()
    .WillCascadeOnDelete(false);
modelBuilder.Entity()
.HasRequired(p=>p.NationOfBirth)
.有很多
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.HasRequired(p=>p.CurrentNationFresidence)
.有很多
.WillCascadeOnDelete(假);

出于测试目的,您能否创建america1、america2等Nation对象,并将其分配给每个人并进行测试?此外,您还必须在person类中使用ForeignKey属性标记NationOfBirth…@Viru刚刚尝试了您的第一个建议。结果是增加了三个“人”,分别是“America1”、“America2”和“America3”(以及三个同名国家)。@Viru WithRequiredDependent()的评论摘要指出——“正在配置的实体类型将是从属的,并且包含主体的外键。关系目标将是关系中主体的实体类型。“-因此我的理解是外键将由modelBuilder命令生成。当然,在代码中建模的优点之一是不需要让不必要的外键属性扰乱代码库。如果CF可以(并且确实)为您添加外键,那么在任何地方添加外键似乎都是不雅观的。你的问题不是这个,而是你正在配置一对一的关系,而实际上你有很多对一的关系,但是你不能有很多第二命令人,只有一个(或零个)。把它收藏起来并不是一个准确的情况模型。嗨,谢谢你的回答,这肯定让我走上了正确的道路。我没有意识到我的modelBuilder配置正在指定一对一关系。我对答案进行了编辑,以将剩余的一个关系所需的配置返回给Person,使其正确,并将其标记为正确。
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();
modelBuilder.Entity<Person>()
    .HasRequired(p => p.NationOfBirth)
    .WithMany()
    .WillCascadeOnDelete(false);
modelBuilder.Entity<Person>()
    .HasRequired(p => p.CurrentNationOfResidence)
    .WithMany()
    .WillCascadeOnDelete(false);