使用多对多和一对多到同一个实体 [英] Using both many-to-many and one-to-many to same entity
问题描述
public class A
{
public int Id {get;组; }
public string Name {get;组; }
public virtual ICollection< B> ObjectsOfB {get;组; }
}
public class B
{
public int Id {get;组; }
public virtual A ObjectA {get;组; }
public virtual ICollection< A> OtherObjectsOfA {get;组; }
}
当我删除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;组; }
public string Name {get;组; }
[InverseProperty(OtherObjectsOfA)]
public virtual ICollection< B> ObjectsOfB {get;组; }
}
这定义了 A.ObjectsOfB
是与 B.OtherObjectsOfA
的多对多关系的一部分。
另一个选项是在Fluent 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)//或HasOptional
.WithMany()
.WillCascadeOnDelete(假); //不确定如果有必要,可以试试
//如果你想要级联删除
}
I have a many-to-many association in EF Code-First (as explained in this question), and I want to use a one-to-many to the same entity as well. The problem is EF does not produce the right database scheme. Code:
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; }
}
When I remove the ObjectA property of class B the many-to-many association is generated correctly. When generated incorrectly, entity B gets 2 foreign keys to A, and entity A gets 1 foreign key to B (like a many-to-one relation).
If you have more than one navigation property refering to the same entity EF does not know where the inverse navigation property on the other entity belongs to. In your example: Does A.ObjectsOfB
refer to B.ObjectA
or to B.OtherObjectsOfA
? Both would be possible and a valid model.
Now, EF does not throw an exception like "cannot determine relationships unambiguously" or something. Instead it decides that B.ObjectA
refers to a third endpoint in B
which is not exposed as navigation property in the model. This creates the first foreign key in table B
. The two navigation properties in B
refer to two endpoints in A
which are also not exposed in the model: B.ObjectA
creats the second foreign key in table B
and B.OtherObjectsOfA
creates a foreign key in table A
.
To fix this you must specify the relationships explicitely.
Option one (the easiest way) is to use the InverseProperty
attribute:
public class A
{
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty("OtherObjectsOfA")]
public virtual ICollection<B> ObjectsOfB { get; set; }
}
This defines that A.ObjectsOfB
is part of a many-to-many relation to B.OtherObjectsOfA
.
The other option is to define the relationships completely in Fluent 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
}
这篇关于使用多对多和一对多到同一个实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!