与实体框架的非键关联

发布于 2024-11-02 11:22:56 字数 1249 浏览 0 评论 0原文

我在实体框架中在两个表之间设置关联时遇到问题,其中关联不包含所有主键值。

例如,我有两个表(这是一个人为的示例,但足以代表我无法更改的真实数据库)

------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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坐在坟头思考人生 2024-11-09 11:22:56

问题是您的数据库设计不正确,并且这些表之间没有关系 - 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 to Item because its FK doesn't contain all parts of Item's PK. In the database this can be avoided by placing unique index on ItemId in the Item 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.

假扮的天使 2024-11-09 11:22:56

您可以使用一种方法并将上下文作为参数,或者简单地创建一个新上下文(至少在 LINQ to SQL 中,根据您的用例,这种情况的惩罚最小),而不是通过“hack”来获取上下文以及我的研究是否有效)。

但是,您正在尝试创建一个条件链接,因此您必须编写一个代表此条件的方法 - 框架基本上执行相同的操作(即选择具有 FK 列中的 ID 的项目)。我不太确定这样做的问题是什么?

我也对你的 ERD 感到非常困惑 - 看起来好像:

  • 项目具有相同的 ID,但随着时间的推移名称不同(在这种情况下我不会将表称为“项目”)
  • 每个订单都是针对一个项目
  • 您试图找出订购时商品的名称。

出于好奇,这是正确的吗?

基于您无法更改 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:

  • Items have the same ID but different names over time (I wouldn't call the table 'Item' in this case)
  • Each order is for one Item
  • You are trying to work out what the name of the item was at the time of the order.

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 as IQueryable<Item>).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文