实体框架DbContext和延迟加载

时间:2019-11-27 11:33:45

标签: c# entity-framework

我想在使用实体框架的应用程序中使用延迟加载,以从数据库中获取数据。我在有关DbContext的答案中读了here

  

应该根据请求创建上下文。

如果我使用这种方式,则会引发以下异常:

  

ObjectContext实例已被处置,不能再用于需要连接的操作。

当然这是因为我在执行查询后删除了上下文。 Here我读到,我可以显式加载数据,但是我不想从其他表中加载数据。

那么您有什么建议,我应该如何使用DbContext才能正确使用延迟加载?

2 个答案:

答案 0 :(得分:4)

您的期望与您目前的执行情况彼此矛盾。

  

我想在应用程序中使用延迟加载

     

ObjectContext实例已被处置,无法再使用

错误消息清楚地表明,关闭上下文后,您仍然期望通过延迟加载访问数据。

这里有两种解决方案:

1。确保在完成延迟加载数据之前不要关闭上下文。

根据设计,这就是您应该进行延迟加载的方式。假设您使用的是using语句,请确保仅在using块中获取数据。

但是,您会注意到,在大型代码库中,很难确保上下文保持足够长的打开时间。我为什么要敦促您考虑其他选择?

2。切换到紧急加载。

惰性加载是一种非常简单的方法,并且在小型应用程序中也可以很好地工作(例如,当我编写短期使用工具来帮助我时)。但是,对于较大的基础架构,延迟加载开始会导致容易犯但难以调试的错误。

尽管急于加载并不能避免这些运行时异常,但与不得不弄清楚哪些数据被延迟加载相比,您将遇到的异常(忘记了Include语句)的调试要容易得多。什么意思。

我不会告诉您不能使用延迟加载,但是您确实需要意识到这会导致复杂性。对于足够大的代码库,保持跟踪是否过早关闭上下文几乎是不可维护的。

维护此代码(以及调试所有您无法避免的问题)的成本将大大超过渴望加载所需的稍微冗长的代码。

答案 1 :(得分:0)

替代延迟加载-每个查询使用DbContext实例。
仅加载当前操作所需的数据,特别是在Web应用程序中,其中应用程序以小块“请求-响应”的形式工作。

DbContext只是一个对象,它的创建是芯片。

延迟加载会很快引入一些问题,例如“ N + 1”查询。

使用每个查询的实例,您将能够充分利用异步查询的优势,在异步查询中,您几乎可以同时执行多个查询。

var orderTask = ordersRepository.Find(orderId);  // Takes 1 second
var invoicesTask = invoiceRepository.FindBy(orderId); // Takes 2 seconds
var deliveriesTask = deliveryRepository.FindBy(orderId); // Takes 3 seconds

await Task.WhenAll(orderTask, invoicesTask, deliveriesTask); 

var order = await orderTask;
var invoices = await invoicesTask;
var deliveries = await deliveriesTask;

如果一个查询一个接一个地执行,则3个查询将在3秒内完成,而不是6个。
单个DbContext不支持同时异步调用。