EF代码首先 - 继承和关系

时间:2012-03-12 20:34:17

标签: c# sql entity-framework

请查看以下代码:

public class SomeEntity
{
    public int Id { get; set; }

    public int UserId { get; set; }
    public virtual User User { get; set; }
}

public class SomeEntityA : SomeEntity
{
    public int Number { get; set; }
}

public class SomeEntityB : SomeEntity
{
    public string Text { get; set; }
}

public class User
{
    public int Id { get; set; }
    public int Username { get; set; }

    public virtual ICollection<SomeEntityA> SomeEntitiesA { get; set; }
    public virtual ICollection<SomeEntityB> SomeEntitiesB { get; set; }
}

我的问题是 - 有没有办法设置FluentApi以使上面显示的关系正常工作?目前,当新的SomeEntityA对象被添加到User时,EF在SomeEntities表中创建了一条新记录并正确设置了User_Id FK,但是在SomeEntitesA这是一个继承的表中,还有一个FK属性User_Id - 设置为null并且当我尝试获取时来自User对象的SomeEntitesA集合 - 它是空的。我确实知道为什么会这样,但我不确定是否有办法解决这个问题?目前我想到的唯一解决方案是替换以下代码:

    public virtual ICollection<SomeEntityA> SomeEntitiesA { get; set; }
    public virtual ICollection<SomeEntityB> SomeEntitiesB { get; set; }

使用:

    public virtual ICollection<SomeEntity> SomeEntitiesA { get; set; }
    public virtual ICollection<SomeEntity> SomeEntitiesB { get; set; }

并配置FluentApi。

任何想法都会受到高度赞赏。

2 个答案:

答案 0 :(得分:1)

您提出的解决方案也不起作用,因为您无法将两个导航属性User.SomeEntitiesAUser.SomeEntitiesB关联到同一个端点SomeEntity.User。您实际上需要两个用户:

public class SomeEntity
{
    public int Id { get; set; }

    public int UserAId { get; set; }
    [InverseProperty("SomeEntitiesA")]
    public virtual User UserA { get; set; }

    public int UserBId { get; set; }
    [InverseProperty("SomeEntitiesB")]
    public virtual User UserB { get; set; }
}

但是,您还可以按原样保留集合类型,并将用户移动到派生实体:

public class SomeEntity
{
    public int Id { get; set; }
}

public class SomeEntityA : SomeEntity
{
    public int Number { get; set; }

    public int UserId { get; set; }
    public virtual User User { get; set; }
}

public class SomeEntityB : SomeEntity
{
    public string Text { get; set; }

    public int UserId { get; set; }
    public virtual User User { get; set; }
}

public class User
{
    public int Id { get; set; }
    public int Username { get; set; }

    public virtual ICollection<SomeEntityA> SomeEntitiesA { get; set; }
    public virtual ICollection<SomeEntityB> SomeEntitiesB { get; set; }
}

在这种情况下,您无需指定[InverseProperty],因为约定会立即检测到正确的导航属性对。

答案 1 :(得分:1)

看一下这个问题/答案,这些课程的结构与你的完全相同,并且详细解释了为什么事情没有按预期工作:

Is inheritance of navigation properties supported?

正如Slauma指出的那样,有一个相当简单的解决方案可以通过执行以下操作来解决这个问题(从链接的答案复制并适合您的示例):

public class User
{
    public int Id { get; set; }
    public int Username { get; set; }

    // this is necessary to have access to the related SomeEntityAs/SomeEntityBs
    // also it cant be private otherwise EF will not overload it properly
    public virtual ICollection<SomeEntity> SomeEntities { get; set; }

    public IEnumerable<SomeEntityA> SomeEntitiesA { get { return this.SomeEntities.OfType<SomeEntityA>(); } }
    public IEnumerable<SomeEntityB> SomeEntitiesB { get { return this.SomeEntities.OfType<SomeEntityA>(); } }
}