想象一下,我想要存储在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
和{{1}之一ReceivedState
和另一个ApprovedState
。这使得很难创建测试数据,因为您不知道哪些字段属于哪些模型。 I asked about this previously.
我采用的解决方案是:
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
,即使它们的行为方式相同而且实现是难以区分的。
由于这几乎没有解决,我现在遇到另一个问题,这导致我提出这个问题:
鉴于我DispatchedState
和BasicState
之间的关系在两个方向上都是多对多,我需要能够从属于{StatefulEntities
的{{1}}中找到订单详细信息1}}。
问题在于虽然这很容易在SQL中表示,但涉及的继承意味着实体框架不知道任何给定的OrderedStates
是否是StatefulEntity
所以似乎没有办法单程访问数据库以包含BasicState
。
所以我不能做的就是这样:
OrderedState
显然,这不是可以运行的代码,但它显示问题是什么 - 订单只属于OrderedState.Order
的某些子类型,所以EF不会预加载它,即使我正在使用某种类型演员。
如果我尝试投影,我可以得到这样的东西:
statefulEntityRepository.Get().Where( x => x.Id == 1 ).Include( x => x.BasicStates ).Include( x.BasicStates.Order );
但是有了这个,我需要找到从投影返回到我的StatefulEntity的匿名类型的方式,以便能够处理它,这感觉就像一个重要的longcut。
我已经尝试定义我的基类和继承者了:
BasicState
依此类推,但后来我似乎打破了首先拥有TPH的基本观点,我觉得好像我也可以在通用数据类上滚动自己的对象模型。
编辑:我想我现在对此有了更多的了解 - 从尝试在该关系的远端设置ForeignKey(即Location和LocationState之间的关系),它看起来好像订单上的逆集合或位置无法与不在基础对象上的属性进行通信,因此我必须使用上面的版本。这为我如何管理没有EntityLocationId或OrderId的案例创造了一个新问题 - 如果我将这些字段设为可空,则会引发一个错误,即在数据库创建期间引用字段不能为空,并且默认情况下无法设置初始值Code First中的字段。
有人可以推荐一种更好的方式来表示可以与Entity Framework一起使用的这种模型吗?