实体框架:一个表中的连接/桥和子

时间:2017-01-24 17:01:35

标签: c# entity-framework

我有一个拥有会员的系统和一个会员家属子表。 Dependent必须始终拥有父成员,但受抚养人也可以自己成为成员。

我在数据库中对此进行建模,如下所示:

CREATE TABLE dbo.MemberDependents(
    ID INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
    MemberID INT NOT NULL REFERENCES dbo.Members (ID) 
        ON UPDATE CASCADE ON DELETE NO ACTION
    MemberObjectID INT -- if not null, this links to what Member they are
);

我的POCO是这样的:

public class Dependent
{
    public int ID { get; set; }
    public int MemberID {get;set;}          // FK
    public int? MemberObjectID {get;set;}   // optional

    public virtual Member Member {get;set;}         // FK
    public virtual Member MemberObject {get;set;}   // optional
}

使用EF的FluentAPI,我映射了通常的FK关系:

modelBuilder<Dependent>()
    .HasRequired(x => x.Member)
    .WithMany(x => x.Dependents)
    .HasForeignKey(x => x.MemberID);

...但是我不确定如何映射那个可选的“这个依赖是一个成员本身,那个成员是......”

modelBuilder<Dependent>()
    .HasOptional(x => x.MemberObject)
    .????
    .HasForeignKey(x => x.MemberObjectID);

如何使用EF FluentAPI映射MemberObject?

更新:(截断的)成员模型:

public class Member
{
    public int ID {get;set;}

    // name, address, etc

    // a few other unrelated properties and methods

    // this is the usual child table
    public virtual ICollection<Dependent> Dependents {Get;set;}

}

成员模型中没有任何内容可以表示来自Dependent的这种奇怪的关系(似乎没有语义来为它添加任何东西......)

作为旁注,我可以在Dependent中使用GetMemberObject()方法进行折腾并手动处理它,但我有点好奇看看如何使用EF来处理它。

1 个答案:

答案 0 :(得分:1)

Member类中有两个Dependent类型的FK属性 - MemberMemberObject,但ICollection<Dependent>中只有一个“反”Member类型属性1}} class。

由于您已将Dependent.Member映射到Member.Dependents,因此您需要添加其他集合,例如

public virtual ICollection<Dependent> DependentOf { get; set;}

并将MemberObject映射到它:

modelBuilder<Dependent>()
    .HasOptional(x => x.MemberObject)
    .WithMany(x => DependentOf)
    .HasForeignKey(x => x.MemberObjectID);

或者如果你想保持关系单向(没有相应的集合),EF为WithXYZ方法专门为这种情况提供无参数重载(相比之下HasXYZ总是需要参数,所以用具有导航属性的实体开始映射是很重要的:

modelBuilder<Dependent>()
    .HasOptional(x => x.MemberObject)
    .WithMany()
    .HasForeignKey(x => x.MemberObjectID);

请注意,所使用的WithXYZ重载应与导航属性的匹配相匹配,否则会出现意外的意外。