想象一下,我有一个要存储在 Entity Framework 4.1 数据存储中的对象层次结构。我正在使用 Code First 创建它们。它们看起来像这样:
BasicState
has many -> StatefulEntities
has a -> CreationDate
ReceivedState
has a -> EntityLocation
ApprovedState
has a -> EntityLocation
OrderedState
has a -> Order
DispatchedState
has a -> Order
has a -> DispatchNumber
BasicState
是所有其他状态的父级,其他所有状态共享这两个字段/关系。
我最初的想法以及我实现这一点的方式是使用 Table Per Hierarchy 继承,因为我似乎可以从BasicState
这些公共属性继承并让我的其他状态参与其中。
然而,这导致了一个问题,因为当不同的状态共享一个字段时,底层数据模型不会,例如,我的数据库将来自EntityLocation_Id
一个ReceivedState
和另一个。这使得创建测试数据变得困难,因为您不知道哪些字段属于哪些模型。我之前问过这个问题。ApprovedState
EntityLocation_Id1
我寻求的解决方案是这样的:
public abstract class BaseState
{
public DateTime CreatedDate { get; set; }
public ICollection<StatefulEntity> StatefulEntities{get;set;}
}
public abstract class LocationState : BaseState
{
public Location EntityLocation { get; set; }
}
public class ReceivedState : LocationState
{
}
public class ApprovedState : LocationState
{
}
这部分工作,但是尽管它创建了一个,但EntityLocation_Id
它仍然Order_Ids
为OrderedState
and创建了两个DispatchedState
,即使它们的行为方式相同并且实现无法区分。
几乎解决了一半,我现在遇到了另一个问题,这导致我问这个问题:
鉴于我 和 之间的关系BasicState
在StatefulEntities
两个方向上是多对多的,我需要能够OrderedStates
从属于 a中找到订单详细信息StatefulEntity
。
问题是,虽然这在 SQL 中很容易表示,但所涉及的继承意味着 Entity Framework 不知道任何给定是否BasicState
为 an OrderedState
,因此似乎无法单次访问数据库以包含OrderedState.Order
.
所以我不能做的是这样的:
statefulEntityRepository.Get().Where( x => x.Id == 1 ).Include( x => x.BasicStates ).Include( x.BasicStates.Order );
显然,这不是可以运行的代码,但它显示了问题所在 - Order 仅属于的某些子类型,BasicState
因此 EF 不会预加载它,即使我正在使用某种类型的演员表。
如果我尝试投影,我会得到这样的结果:
statefulEntityRepository.Get().Select( x=> new {
StatefulEntity = x,
EntityLocation = ( from state in x.BaseStates where state is ReceivedState select state.EntityLocation )
}
但是,我需要找到从投影返回的匿名类型返回到我的 StatefulEntity 的方法,以便我的其余代码能够处理它,这感觉像是一个重要的长切。
我已经尝试这样定义我的基类和继承者:
public abstract class BaseState
{
public DateTime CreatedDate { get; set; }
public ICollection<StatefulEntity> StatefulEntities{get;set;}
public long EntitytLocationId { get; set; }
}
public abstract class LocationState : BaseState
{
[Column(name="EntityLocationId")]
public Location EntityLocation { get; set; }
}
依此类推,但我似乎打破了首先拥有 TPH 的基本点,我觉得我还不如在通用数据类上滚动我自己的对象模型。
编辑:我想我现在对此有了更多的了解-从尝试将 ForeignKey 设置在该关系的远端(即 Location 和 LocationState 之间的关系),它看起来好像 Order 或 Location 上的反向集合可以'不要与不在基础对象上的属性交谈,所以我必须使用上面的版本。这在我如何管理没有 EntityLocationId 或 OrderId 的案例时产生了一个新问题——如果我将这些字段设为可为空,则会引发一个错误,即在数据库创建期间引用字段不能为空,并且默认情况下无法在代码优先中的字段。
任何人都可以推荐一种更好的方法来表示可以与实体框架一起使用的这种类型的模型吗?