繁体   English   中英

实体框架 DbContext 和延迟加载

[英]Entity framework DbContext and lazy loading

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

应根据请求创建上下文。

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

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

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

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

你的期望和你目前的执行是相互矛盾的。

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

ObjectContext 实例已被释放,无法再使用

错误消息清楚地表明您在关闭上下文后仍然希望访问数据(通过延迟加载),这是不可能的。

这里有两种解决方案:

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

按照设计,这就是您假设进行延迟加载的方式。 假设您使用的是using语句,请确保您只在using块内获取数据。

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

2. 切换到急切加载。

延迟加载是一种非常简单的方法,并且在小型应用程序中运行良好(例如,当我编写一个短期使用工具来帮助我时)。 然而,对于较大的基础设施,延迟加载开始导致容易犯但很难调试的错误。

虽然预先加载并不能避免这些运行时异常,但与必须弄清楚哪些数据在什么时候被延迟加载相比,您将遇到的异常(忘记了Include语句)将更容易调试。

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

维护这个(和调试所有你没有阻止的问题)的成本将大大超过预先加载所需的稍微冗长的代码。

延迟加载的替代方案 - 每个查询使用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 秒内完成,而不是 6 秒。
单个 DbContext 不支持同时异步调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM