因此,我管理了一个相当大的 Web 应用程序,并设置了一种独特的方法来处理我的 Entity Framework 数据上下文,以帮助缓存页面上的不同事件。从我之前看到的情况来看,基本上有两种方法可以在实体框架中跨页面管理上下文:
- 创建一个为所有连接共享的静态上下文。
- 在您的活动中将连接用作一次性连接。
因为我们的数据变化太快,我不想使用静态上下文,所以我最初从每个事件中的一次性连接开始。这变得有问题,因为我们的页面相当健壮,并且由于不断打开和关闭上下文而导致大量开销。此外,这限制了我可以在页面中执行的缓存量,因为我必须为每个事件带来新鲜的数据。最后,我决定采用一种我从未见过的新方法,即为每个请求打开一个上下文,并为整个请求保持打开状态。这在两种方法之间提供了最佳的灵活性,代码如下:
public class FrontEndPage : System.Web.UI.Page
{
private PageContext _context;
public Database.DatabaseEntities context
{
get
{
if (_context == null)
_context = new PageContext();
return _context.Context;
}
}
}
public class PageContext
{
public Database.DatabaseEntities Context;
public PageContext()
{
Context = Database.DatabaseEntities();
}
}
这导致了一个新的有趣的问题。我开始收到连接到数据库的间歇性错误。一旦我刷新应用程序池,它就会消失。我唯一能找到的解释是,我处理数据库上下文的方法中的实体连接并不总是正确处理,并且当垃圾收集无法清除它们时,最终会留下打开的连接。大约一天后,它耗尽了 Sql Server 的连接限制并导致以下错误。
Named Pipes Provider, error: 40 - Could not open a connection to SQL Server
Server Error in '/' Application.
Access is denied
Description: An unhandled exception occurred during the execution of the current web equest. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ComponentModel.Win32Exception: Access is denied
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
从那时起,我将应用程序池的回收计划更新为 4 小时增量,但这并不是真正的永久解决方案。由于我缓存的方式,我肯定想找到一种方法来使每个请求 1 个上下文的方法工作,因为它非常适合应用程序,但我需要一种方法来确保正确关闭任何打开的上下文。
有没有更好的方法来处理这个问题,或者有一种方法可以确保在请求完成后关闭这个连接,我可以用它来防止它让连接挂起?
还是错误可能是由其他原因引起的?