我在实体框架中设置两个表之间的关联时遇到问题,该关联不包含所有主键值。
。我有两个表(这是一个人为的例子,但它足以表示我无法更改的真实数据库)
------Items------ ---Orders----
----------------- -------------
* ItemId - * OrderId -
* EffectiveDate - - OrderDate -
- Name - - ItemId -
----------------- ------------- * denotes primary key field
理想情况下,我希望在Orders上有一个属性,指示在OrderDate有效的Item,但是我可以在Order上与Item集合建立关联,然后在Order上创建一个只读属性,选择正确的Item。
编辑:数据库和模型将是只读的,所以只读解决方案是可以的。这在实体框架中是可能的吗?(甚至从LINQ到SQL?)
我相信使用NHibernate是可能的(有人能确认吗?)但是我一直在实体框架上碰壁。到目前为止,我管理的唯一解决方案是在Order的部分类中创建一个属性,该属性使用"hack"从Order访问ObjectContext并查询上下文。
private IEnumerable<Item> Items
{
get
{
var ctx = this.GetContext();
return from i in ctx.Items where i.ItemId == this.ItemId select i;
}
}
public Item Item
{
get
{
return (from i in Items
where i.EffectiveDate <= this.OrderDate
orderby i.EffectiveDate ascending
select i).First();
}
}
有更好的解决方案吗?
问题是你的数据库设计不正确,这些表之间没有关系- Order
不能与Item
有FK关系,因为它的FK不包含Item的PK的所有部分。在数据库中,这可以通过在Item
表的ItemId
上放置唯一索引来避免,但它使你的复合PK冗余,它不能解决EF的问题,因为EF不支持唯一键。也不能映射多对多关系,因为缺少连接表。
所以EF的答案是否定的。同样的答案也适用于linq-to-sql。
与其"破解"获取上下文,不如使用方法并将上下文作为参数,或者简单地创建一个新上下文(至少在LINQ to SQL中,这取决于您的用例以及我的研究是否有效)。
然而,你试图创建一个条件链接,所以你将不得不写一个方法表示这个条件-框架基本上是做同样的事情(即选择项目与ID在FK列)。我不太确定这样做有什么问题?
我也完全被你的ERD搞糊涂了——看起来好像:
- 项目有相同的ID,但随着时间的推移不同的名称(我不会叫表'Item'在这种情况下)
- 每个订单是一个项目
- 您正在尝试找出订购时的商品名称。
出于好奇,这是正确的吗?
基于您无法更改ERD的事实,您提到的方法可能是实现这一目标的最佳方法(尽管您可能希望将Items
标记为IQueryable<Item>
)。