SQL连接限制和管理实体

时间:2013-08-15 19:18:38

标签: c# asp.net entity-framework sql-server-2008-r2 garbage-collection

因此,我管理了一个相当大的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();
    }
} 

这导致了一个新的有趣的问题。我开始收到连接到数据库的间歇性错误。刷新应用程序池后,它就会消失。我唯一能解释的是,我处理db上下文的方法中的实体连接并不总是正确处理,并且当Garbage Collection无法清除它们时最终会保持打开连接。大约一天后,它耗尽了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个上下文的方法工作,因为它非常适合应用程序,但我需要一种方法来确保正确关闭任何打开的上下文。

有没有更好的方法来处理这个或确保在请求完成后关闭此连接的方法,我可以使用它来防止它让连接挂起?

或者错误可能是由其他原因引起的?

1 个答案:

答案 0 :(得分:0)

所以,我设法找到了最佳解决方案。我在自定义页面类中添加了一个页面卸载事件,用于检查是否存在打开的上下文并关闭连接。在这一点上,这是我发现处理连接的最佳方法,因为它提供了保持缓存和确保对象始终是最新的最大平衡。

protected void Page_Unload(Object sender, EventArgs e)
{
    if (_context != null)
    {
        if (_context.Context.Connection.State == ConnectionState.Open)
            _context.Context.Connection.Close();
        _context.Context.Dispose();
        _context.Context = null;
        _context = null;
    }
}