0

我已经踢上ADO EF代码第一次轮胎,并拿出了以下问题:ADO EF代码第一次双向许多一对多的自我参照的挑战

我的模型很简单,代表一个家庭树。 它由一个具有几个标量属性的人物类名字等组成, 表示父母的人物集合和 另一个表示儿童人物集合。

public class Person 
{ 
    public int id { get; set; } 
    public string FirstName { get; set; } 
    public string MiddleName { get; set; } 
    public string LastName { get; set; } 
    public DateTime? DateOfBirth { get; set; } 

    List<Person> children = new List<Person>(); 
    public IList<Person> Children { get { return children; } set { children = (List<Person>)value; } } 

    List<Person> parents = new List<Person>(); 
    public IList<Person> Parents { get { return parents; } set { parents = (List<Person>)value; } } 
} 

上下文代码非常简单

public class DataContext : DbContext 
{ 
    public DbSet<Person> People { get; set; } 
} 

时生成为预期的数据库架构。 人员表与2个名为PersonPersons的表的一对多关系。 (顺便说一下,是否有改变这个名为FamilyTree的表?)

然后,我开始使用一些数据种子数据库,这是一个流行的辛普森卡通节目的家谱。 我创建了我需要的所有人,将它们关联起来,然后保存代表Homer Simpson的人物变量。

class ProjectDBInitializer : DropCreateDatabaseIfModelChanges<DataContext> 
{ 
    protected override void Seed(DataContext context) 
    { 
     Person ph = new Person() { FirstName = "Homer", LastName = "Simpson" }; 
     Person pm = new Person() { FirstName = "Marge", LastName = "Simpson" }; 

     Person pb = new Person() { FirstName = "Bart", LastName = "Simpson" }; 
     Person pl = new Person() { FirstName = "Lisa", LastName = "Simpson" }; 

     Person phf = new Person() { FirstName = "GranPa", LastName = "Simpson" }; 
     Person phm = new Person() { FirstName = "GranMa", LastName = "Simpson" }; 

     Person pmf = new Person() { FirstName = "Marge Father", LastName = "Maiden" }; 
     Person pmm = new Person() { FirstName = "Marge Mother", LastName = "Maiden" }; 

     phf.Children.Add(ph); 
     phm.Children.Add(ph); 

     ph.Children.Add(pb); 
     ph.Children.Add(pl); 

     pb.Parents.Add(ph); 
     pb.Parents.Add(pm); 

     pl.Parents.Add(ph); 
     pl.Parents.Add(pm); 

     pm.Parents.Add(pmf); 
     pm.Parents.Add(pmm); 

     context.People.Add(ph); 
     context.SaveChanges(); 
    } 
} 

当我看着数据库中发生了什么时,问题就会出现。

已经插入了所有Marge的家庭,但荷马的父母(GranPa和GranMa)没有。 我认为这与这个事实有关,即即使他们在他们的Children集合中引用它,ph varibale也没有提及它们。

什么是解决这个问题最好的(最简单的)方法?

+0

我已经注意到更多要添加到拉迪斯拉夫的答案,请阅读并接受它作为答案:) – 2011-04-22 22:02:16

回答

2

要reneme表必须添加流利的映射到您的上下文:

public class DataContext : DbContext 
{ 
    public DbSet<Person> People { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Entity<Person>() 
      .HasMany(p => p.Children) 
      .WithMany(c => c.Parents) 
      .Map(m => m.ToTable("FamilyTree")); 
    } 
} 

与插入的问题是完全按照你描述。如果您想插入荷马,您必须将phf和phm设置为他的父母,或者您必须将phm和phf添加到与您添加荷马相同的方式设置的人。

自动生成的POCO对象(用于从EDMX生成POCO的T4模板)使用更复杂的导航属性代码,并且它们在内部处理关系修正,因此如果您在phm中将Homer添加到子集合中,它将自动将phm添加到Homer父母。如果你想在你自己的POCO中使用这样的功能,你必须自己实现它。修正方法并不总是双赢的解决方案,因为它们有一些缺点,有时会触发延迟加载而无需加载数据。

+0

+1尼斯答案:) – 2011-04-22 22:00:34

+0

非常感谢您的答复。这是我担心的!我需要编写更多的代码。我研究了POCO类正在做什么,将它放到模板中是有意义的。这是重复和无聊:)这就是说我惊讶的代码第一引擎没有提供任何处理proplem看到它正确地传递了关系,当然它可以实现某种图形遍历来修复关系之前致力于D B。我会自己试一试。干杯。 – Hugo 2011-04-23 16:20:34