EF代码优先-继承和关系
本文关键字:继承 关系 代码 EF | 更新日期: 2023-09-27 18:27:38
请查看以下代码:
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会在SomeEntity表中创建一个具有正确设置的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。
如有任何想法,我们将不胜感激。
看看这个问题/答案,这些类的结构与您的完全相同,并且有一个详细的解释,解释了为什么事情没有按预期工作:
是否支持导航属性的继承?
正如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>(); } }
}
您提出的解决方案也不起作用,因为您无法将两个导航属性User.SomeEntitiesA
和User.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]
,因为约定现在将检测到正确的导航属性对。