与实体框架的非键关联
我在实体框架中在两个表之间设置关联时遇到问题,其中关联不包含所有主键值。
例如,我有两个表(这是一个人为的示例,但足以代表我无法更改的真实数据库)
------Items------ ---Orders----
----------------- -------------
* ItemId - * OrderId -
* EffectiveDate - - OrderDate -
- Name - - ItemId -
----------------- ------------- * denotes primary key field
理想情况下,我希望 Orders 上有一个属性,该属性指示在 OrderDate 有效的项目,但我可以接受订单与项目集合的关联,然后在选择正确项目的订单上创建只读属性。
编辑:数据库和模型将是只读的,因此只读解决方案是可以的。
这在实体框架中可能吗? (或者甚至是 LINQ to SQL?)
我相信使用 NHibernate 是可能的(有人能确认吗?)但我一直用实体框架碰壁。到目前为止,我管理的唯一解决方案是在 Order 的分部类中创建一个属性,该属性使用 'hack' 从 order 访问 ObjectContext 并直接查询 context.Items 集合是否
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();
}
}
有更好的解决方案?
I am having problems setting up an association in entity framework between two tables where the association does not contain all the primary key values.
e.g. I have two tables (this is a contrived example, but it is sufficient to represent my real database which I cannot change)
------Items------ ---Orders----
----------------- -------------
* ItemId - * OrderId -
* EffectiveDate - - OrderDate -
- Name - - ItemId -
----------------- ------------- * denotes primary key field
Ideally I'd like a property on Orders that indicates the Item that was effective at OrderDate, but I could live with an association on Order to a collection of Items and then create a readonly property on Order that selected the correct Item.
EDIT: The database and model will be read-only so read-only solutions are OK.
Is this possible in entity framework? (or even LINQ to SQL?)
I believe that it is possible using NHibernate (can anyone confirm?) but I keep hitting brick walls with entity framework. So far the only solution I have managed is to create a property in the partial class for Order that uses a 'hack' to access the ObjectContext from order and query the context.Items collection directly as such
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();
}
}
Is there a better solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是您的数据库设计不正确,并且这些表之间没有关系 -
Order
不能与Item
有 FK 关系,因为它的 FK 不包含 Item 的所有部分PK。在数据库中,可以通过在Item
表中的ItemId
上放置唯一索引来避免这种情况,但这会使您的复合 PK 冗余,并且不能解决 EF 的问题,因为 EF不支持唯一键。多对多关系也无法映射,因为缺少连接表。所以EF的答案是否定的。同样的答案也适用于 linq-to-sql。
The problem is that your database is incorrectly designed and there is no relationship between those tables -
Order
cannot have FK relation toItem
because its FK doesn't contain all parts of Item's PK. In the database this can be avoided by placing unique index onItemId
in theItem
table but it makes your composite PK redundant and it doesn't solve the problem for EF because EF doesn't support unique keys. Many-to-many relation cannot be mapped as well because you are missing junction table.So the answer for EF is no. The same answer will be for linq-to-sql.
您可以使用一种方法并将上下文作为参数,或者简单地创建一个新上下文(至少在 LINQ to SQL 中,根据您的用例,这种情况的惩罚最小),而不是通过“hack”来获取上下文以及我的研究是否有效)。
但是,您正在尝试创建一个条件链接,因此您必须编写一个代表此条件的方法 - 框架基本上执行相同的操作(即选择具有 FK 列中的 ID 的项目)。我不太确定这样做的问题是什么?
我也对你的 ERD 感到非常困惑 - 看起来好像:
出于好奇,这是正确的吗?
基于您无法更改 ERD 的事实,您提到的方法可能是实现这一目标的最佳方法(尽管您可能希望将
Items
标记为IQueryable- < /代码>)。
Rather than a "hack" to get a context, you could use a method and take a context as a parameter, or simply create a new context (in LINQ to SQL at least, there is minimal penalty for this depending on your use-case and if my research is valid).
However, you're trying to create a conditional link, so you are going to have to write a method representing this condition - the frameworks are doing basically the same thing (i.e. selecting the Item with the ID in the FK column). I'm not exactly sure what the issue is in doing that?
I'm also thoroughly confused by your ERD - it seems as though:
Out of curiosity, is this correct?
Based on the fact you can't change your ERD, the method you've mentioned is probably the best way to achieve that (although you might want to mark
Items
asIQueryable<Item>
).