我首先使用Entity Framework 4.3代码。如何在A类中的两个属性和B类中的集合之间创建两个“一对多”关系?
我的模特:
public class Shaft
{
public int Id { get; set; }
public virtual Coupling FirstEnd { get; set; }
public virtual Coupling SecondEnd { get; set; }
}
public class Coupling
{
public int Id { get; set; }
public virtual ICollection<Shaft> Shafts { get; set; }
}
答案 0 :(得分:2)
嗯,一对多关系被称为一个对多,因为关系的第一端有一个元素,而且很多元素都在另一端。您还可以拥有零或一个到多个关系,这只表示非多方面的元素可以是null
(或数据库中的NULL
)
您要定义的是两个到多个(或者可能是零或一个或两个到多个)关系。这样的事情在关系数据库中不存在,也不存在于实体框架中。
当您使用EF定义关系时,您需要在源类和目标类中使用两个导航属性的对。 可以省略导航属性的一个,但这并不意味着您可以将此关系的结尾移动到另一个已属于另一个关系的导航属性。< / p>
在您的特定情况下,您有两种关系,因为FirstEnd
中的两个导航属性SecondEnd
和Shaft
代表两个不同的外键。因此,您需要Coupling
中的两个集合,或者您可以将现有属性Coupling.Shafts
与FirstEnd
或SecondEnd
相关联,但不能同时与两者相关联。另一个引用将引用Coupling
中的“不可见”未公开的导航集合。 (这是您自己的答案中的映射会发生的情况:EF将采用覆盖第一个映射块的第二个映射块,在SecondEnd
和Shafts
之间创建关系,然后在{{1并且未公开的关系会再次以FirstEnd
,而不是 Coupling
结束。)
具有两个集合的解决方案 - 在我看来更有意义 - 看起来像这样:
Shafts
这个映射:
public class Coupling
{
public int Id { get; set; }
public virtual ICollection<Shaft> ShaftsWithFirstEndHere { get; set; }
public virtual ICollection<Shaft> ShaftsWithSecondEndHere { get; set; }
}
您可以创建一个只读的,没有映射助手属性,以连接两个集合togother一个集合,但已经被加载了两个导航集合后连接将在内存中发生:
modelBuilder.Entity<Coupling>()
.HasMany(x => x.ShaftsWithFirstEndHere)
.WithOptional(x => x.FirstEnd);
modelBuilder.Entity<Coupling>()
.HasMany(x => x.ShaftsWithSecondEndHere)
.WithOptional(x => x.SecondEnd);
没有任何一种映射可以自动进行这种连接。请注意,一对多关系中的导航集合属性只是依赖表中的外键查询的结果(在您的示例中为= public class Coupling
{
public int Id { get; set; }
public virtual ICollection<Shaft> ShaftsWithFirstEndHere { get; set; }
public virtual ICollection<Shaft> ShaftsWithSecondEndHere { get; set; }
// not mapped to DB because it has only a getter = readonly
public IEnumerable<Shaft> Shafts
{
get { return ShaftsWithFirstEndHere.Concat(ShaftsWithSecondEndHere); }
}
}
)。其被用于填充的集合外键(通过使用Shaft
,例如,或当迟缓装载被触发)是公由关系映射定义,它只有一个键 - 无论是对键Include
或FirstEnd
的关键,但不是两者。您要实现的是两个不同外键的两个查询的组合连接结果。对于关系映射,这是不可能的。