执行该命令需要一个开放和可用的连接。连接当前状态已中断。

6
在 qa 中使用一段时间后,我们遇到了以下错误:
执行命令需要一个打开且可用的连接。连接的当前状态已经中断。
我们正在使用 EntityFramework 的单例实例。
SOF 建议:
1) 偶尔创建一个新的 ContectObject 实例
2) 配置池连接数更高
解决这个问题的最佳实践是什么?
我认为为每个 Dal 操作创建一个新的 contectObject 是浪费的。
2个回答

11

我认为为每个Dal操作创建新的contectObject是浪费的。

你有任何证据支持这个观点吗?我相信Entity Framework和大部分数据访问框架都是为短暂且独立的上下文设计的。在此处实现自己的池/缓存通常是反模式,可能导致过期结果、并发问题和恢复失败(就像这里一样)。

您认为会浪费哪些具体资源,并且是否已经通过实验进行了验证?

基本上,我建议为每个工作单元(可能大致对应于请求)创建一个新的上下文-测量任何性能差异,并检查问题是否消失(正如我所预期的那样)。作为测试的一部分,偶尔断开数据库服务器与网络的连接以检查您是否可以真正恢复...


1
我们预计将会有大规模请求(即使在CDN之后)。我认为“打开”和“关闭”连接是昂贵的操作,更不用说在应用堆中创建和存储许多对象了。 - Elad Benda
4
你是认为还是有实证证据支持这个观点?不要忘记应用层下面已经有连接池了。至于对象:短生命周期的对象相对于长生命周期的对象在垃圾回收方面更加廉价。 - Jon Skeet
现在我对每个单元使用新的contextObject进行using。但是我的BL代码使用这些对象,我得到了这个异常:System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. - Elad Benda
@EladBenda:没错 - 所以听起来你的上下文现在太狭窄了,因为它没有包含完整的工作单元。你应该基本上在需要的时候保持上下文,但不要超过需要的时间。 - Jon Skeet
但后来我混合了层次:BL 和 Dal。在 BL 中实例化 contextObject 并不可维护,因为它是 Dal 对象。 - Elad Benda

2
请阅读关于连接池的内容。
当您处置EF上下文时,您正在处置基础存储提供程序连接。但是,当您处置存储连接时,默认情况下不会关闭任何传输级别的连接,除非您已明确关闭连接池。
此外,EF每个应用程序域缓存元数据视图。
因此,EF上下文创建非常便宜
还要记住,在每个上下文实例中都有更改跟踪器。当您有单个上下文时,其更改跟踪器跟踪通过上下文实现或附加到上下文的所有内容。 “跟踪所有内容”意味着您通过上下文检索的每个实体实例都不会被处置-跟踪器保留对其的引用。
不要创建长时间存在的上下文实例。

现在,我对每个单元使用新的contextObject using。 但是我的BL代码使用这些对象并出现异常:System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. - Elad Benda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接