对同一实体使用多对多和一对多

问题描述:

我在EF Code-First中有一个多对多关联(如this问题所述),我想使用one-to对同一个实体也是如此。问题是EF不会产生正确的数据库方案。代码:对同一实体使用多对多和一对多

public class A 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<B> ObjectsOfB { get; set; } 
} 

public class B 
{ 
    public int Id { get; set; } 
    public virtual A ObjectA { get; set; } 
    public virtual ICollection<A> OtherObjectsOfA { get; set; } 
} 

当我删除B类的ObjectA属性时,正确地生成了多对多关联。 当生成不正确时,实体B将2个外键获取给A,并且实体A获得1个B外键(如多对一关系)。

如果您有多个导航属性引用同一个实体,EF不知道其他实体的逆导航属性属于哪里。在你的例子中:A.ObjectsOfB是指B.ObjectA还是B.OtherObjectsOfA?两者都是可能的,而且是有效的模型。

现在,EF不会抛出像“无法明确确定关系”之类的异常。相反,它决定B.ObjectA引用B中的第三个端点,该模型中未显示导航属性。这将在表B中创建第一个外键。 B中的两个导航属性指的是A中的两个端点,它们在模型中也未公开:B.ObjectA创建表B中的第二个外键,B.OtherObjectsOfA在表A中创建外键。

要解决此问题,您必须明确指定关系。

选项之一(最简单的方法)是使用InverseProperty属性:

public class A 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    [InverseProperty("OtherObjectsOfA")] 
    public virtual ICollection<B> ObjectsOfB { get; set; } 
} 

这定义了A.ObjectsOfB是许多一对多关系B.OtherObjectsOfA的一部分。

另一种选择是,以流利的API完全定义的关系:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<A>() 
     .HasMany(a => a.ObjectsOfB) 
     .WithMany(b => b.OtherObjectsOfA) 
     .Map(x => 
     { 
      x.MapLeftKey("AId"); 
      x.MapRightKey("BId"); 
      x.ToTable("ABs"); 
     }); 

    modelBuilder.Entity<B>() 
     .HasRequired(b => b.ObjectA) // or HasOptional 
     .WithMany() 
     .WillCascadeOnDelete(false); // not sure if necessary, you can try it 
             // without if you want cascading delete 
} 
+0

谢谢你的回答!但是,对于这两种解决方案,我都会得到以下异常:'在EntityFramework.DLL中发生'System.InvalidOperationException'类型的第一次机会异常' – Marthijn

+0

更正:流畅的解决方案(我的错误..),非常感谢!任何想法为什么'InverseProperty'引发异常? – Marthijn

+0

@Henkie:应用程序真的崩溃吗? “第一次机会异常”通常不是问题,只在调试器输出窗口中显示。通常它可以被忽略。 – Slauma

如果表B具有表A的外键,那么类B具有导航属性到A,导航属性为ICollection<A>
如果表B与表A有多对多的关系,那么A级必须有ICollection<B>,B级必须有ICollection<A>

尝试一下,也许这会明确你的要求从EF。

+0

我忘了ICollection中添加'类A'在我的代码示例中的许多-to-many关联。现在已经修复了。 – Marthijn

+0

@Henkie:很高兴能帮到你:) – Naor