【问题标题】:How can I attach EF sub-entities to an EF entity?如何将 EF 子实体附加到 EF 实体?
【发布时间】:2013-08-08 17:36:49
【问题描述】:

假设我有一个 Order 实体和一个 OrderItem 实体,并且我试图一次获取多个订单的详细信息(包括商品)。

我可以像这样使用.Include 将订单和订单项详细信息一起获取:

var orders = db.Orders
               .Include(o => o.OrderItem)
               .Where(o => orderIds.Contains(o.Id));

但是,假设我不能使用.Include,因为it doesn't work

相反,我可以获取所有订单,然后获取所有订单项,如下所示:

var orders = db.Orders.Where(o => orderIds.Contains(o.Id));

var orderItems = db.OrderItems.Where(i => orderIds.Contains(i.OrderId));

这将为我提供所有订单和(单独)所有相关的订单项。但是如何将OrderItem 对象“附加”到相关的Order 对象,以便导航属性正常工作?

(换句话说,我如何确保order.OrderItemsorderItem.Order 在不导致EF 从数据库中获取数据而不是使用我已经检索到的数据的情况下工作)。

【问题讨论】:

  • 您是否尝试过切换 EF 的代理生成(包括延迟加载)并在代码中设置导航探针?
  • 只要关系不是多对多并且没有禁用更改跟踪,它应该会自动将所有加载的OrderItems 添加到正确的Order 的导航集合中s(称为“关系修正”)。你测试了吗?不行吗?
  • @Slauma:谢谢,它看起来正在工作。让我感到困惑的是,检查调试器中的实体会导致由于某种原因重新获取数据。如果我避免使用调试器,而是访问代码中的各种成员,那么它似乎不会回到数据库。您能否将您的评论转换为答案,以便我接受并关闭问题?
  • @Slauma: ...但是等等-根据msdn.microsoft.com/en-US/data/jj691402“如果你启用了延迟加载,访问博客实体之一上的posts属性,那么EF将连接到数据库以延迟加载所有帖子,即使我们已经加载了所有帖子。这是因为 EF 无法知道您是否已加载所有帖子或数据库中是否还有更多帖子。如果您想避免这种情况,则需要禁用延迟加载“ .所以大概我在这里会遇到同样的问题。 (我的实际场景并不像我描述的那么简单,所以我很难测试)。
  • 对于 EF5,我现在正在做的是禁用 EF 的延迟加载,并在我自己的项目中完全在需要的地方处理延迟加载。 IIRC,EF6 将提供将导航集合属性标记为已加载的选项。您是否可以选择升级到 EF 的预发布版本?

标签: entity-framework entity-framework-5


【解决方案1】:

关于你的最后一个问题——how do I ensure that order.OrderItems and orderItem.Order work without causing EF to go fetch the data from the database ...——你可以先.Load()你的查询进入内存:

orders.Load();
orderItems.Load();

然后通过上下文的Local 属性使用它们:

var qo = db.Orders.Local.Where(...);
var qoi = db.OrderItems.Local.Where(...);

【讨论】:

  • 这并没有回答问题:正如问题的 cmets 中已经提到的那样,在此之后,qo.First().OrderItems仍然如果启用延迟加载会转到数据库.
  • @hvd - 当然是它导致的!他只能使用Local 属性。甚至qo.First().OrderItems 也会进行数据库查询。事实上,内存中的集合存储在Local 属性中,对除Locals 之外的任何集合的任何查询都会导致数据库查询...
  • qo你的 qo,即db.Orders.Local.Where(...)。完全扩展它,我说db.Orders.Local.Where(...).First().OrderItems 将导致执行数据库查询。即使它从db.Orders.Local 开始。一个好的答案可能应该显示如何避免这种情况。问题具体包括“我如何确保 order.OrderItems 和 orderItem.Order 工作而不会导致 EF 去获取数据 [...]”
  • @hvd - 我理解你,但我无法表达我的意思...... Locals 中存在的数据没有问题。但是,如果您正在寻找一些本地不存在的数据,它确实会导致一个新的查询来获取那些丢失的数据......事实上,首先,您应该预见哪些数据应该在内存中,然后加载它们并使用它们...
  • 数据 已经在内存中可用,如果禁用延迟加载,order.OrderItems 已经完全按照 OP 的预期方式工作。然后order.OrderItems 将只查看本地检索到的订单项目:它会查看您也可以从db.OrderItems.Local.Where(orderItem => orderItem.Order == order) 获得的那些项目。无论如何,解释它为什么不起作用但不解释如何使它起作用是不够的。
【解决方案2】:

为了结束这个问题,这是我所做/学到的:

1) 正如 Slauma 在他的评论中指出的那样,即使 OrdersOrderItems 是单独获取的,EF 确实修复了导航属性,因此例如每个 OrderItem 的 Order 属性正确地指向正确的 @ 987654323@.

2) 不幸的是,EF 无法知道 所有 订单的 OrderItems 已被获取,因此如果 Order.OrderItems 导航属性是延迟加载的,则访问该属性将导致 EF 从数据库中重新获取所有 OrderItem 数据 - 它会在每个 Order 中执行一次。显然不好。

3) 避免上述问题的唯一方法似乎是删除该集合属性上的延迟加载(以及其他类似的集合 - 一对一的导航属性不受此问题的影响)。

【讨论】:

    猜你喜欢
    • 2019-01-18
    • 2020-05-31
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    相关资源
    最近更新 更多