2012-01-30 28 views
11

我希望有人可以幫我解決以下錯誤。發生錯誤的應用程序在生產環境中運行,我從不親自體驗錯誤。然而,每天大約20次,我收到一封錯誤郵件告訴我:使用EF4(edmx模式)時偶爾會出現「底層提供程序無法打開」錯誤

底層提供程序在打開時失敗。 ---> System.InvalidOperationException:連接未關閉。 連接的當前狀態正在連接。

這裏的堆棧跟蹤

System.Data.EntityException:底層提供失敗的打開。 ---> System.InvalidOperationException:連接未關閉。連接的當前狀態正在連接。在在 System.Data.SqlClient.SqlConnection.Open() System.Data.ProviderBase.DbConnectionBusy.OpenConnection(的DbConnection outerConnection,DbConnectionFactory connectionFactory的)在 HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledConnection.Open() 在 System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(布爾 openCondition,的DbConnection storeConnectionToOpen,的DbConnection originalConnection,字符串exceptionCode,字符串attemptedOperation, 布爾& closeStoreConnectionOnFailure)---內部異常 堆棧跟蹤的末尾在 System.Data .EntityClient.EntityConnection.OpenStoreConnectionIf (布爾 openCondition,的DbConnection storeConnectionToOpen,的DbConnection originalConnection,字符串exceptionCode,字符串attemptedOperation, 布爾& closeStoreConnectionOnFailure)處 System.Data.Objects.ObjectContext.EnsureConnection System.Data.EntityClient.EntityConnection.Open()(),在 System.Data.Objects.ObjectQuery forMergeOption)在 System.Data.Objects.ObjectQuery 源)在 System.Data.Objects.ELinq.ObjectQueryProvider.b__1 [TResult](IEnumerable的查詢, Expression queryRoot)at Sys tem.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute [S](式 表達)在 System.Linq.Queryable.FirstOrDefault [TSource](IQueryable`1源)
在 GuideSites.DomainModel .Repositories.ClinicTermRepository.GetClinicTermByGuideSiteId(的Int32 guideSiteId)在 C:\項目\ GuideSites \ GuideSites.DomainModel \庫\ ClinicTermRepository.cs:線 20在 GuideSites.Web.Frontend.Helpers.VerifyUrlHelper.RedirectOldUrls() C:\ Projects \ GuideSites \ GuideSites.Web.Frontend \ Helpers \ VerifyUrlHelper.cs:line 91 at GuideSites.Web.Frontend.MvcApplication.Application_BeginRequest(Object sender,EventArgs e) C:\ Projects \ GuideSites \ GuideSites.Web.Frontend \ Global.asax.cs:412行 at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute( )在System.Web.HttpApplication處爲 。ExecuteStep(IExecutionStep步驟, 布爾& completedSynchronously)

我使用EF4通過EDMX模型和我的方式予連接到數據庫(MS SQL 2008)是通過一個HttpContext的基於每個請求對象上下文,以便對於給定頁面加載所需的每一條數據,都不會打開和關閉與數據庫的連接。

我的數據庫上下文類看起來是這樣的:

public class DatabaseContext : IDisposable 
{ 
    private const string ContextName = "context"; 
    private static dbEntities _dbEntities; 

    public dbEntities GetDatabaseContext() 
    { 
     SqlConnection.ClearAllPools(); 

     if (HttpContext.Current == null) 
      return _dbEntities ?? (_dbEntities = new dbEntities()); 

     if (HttpContext.Current.Items[ContextName] == null) 
      HttpContext.Current.Items[ContextName] = new dbEntities(); 

     _dbEntities = (dbEntities)HttpContext.Current.Items[ContextName]; 
     if (_dbEntities.Connection.State == ConnectionState.Closed) 
     { 
      _dbEntities.Connection.Open(); 
      return _dbEntities; 
     } 

     return _dbEntities; 
    } 


    public void RemoveContext() 
    { 
     if (HttpContext.Current != null && HttpContext.Current.Items[ContextName] != null) 
     { 
      ((dbEntities)HttpContext.Current.Items[ContextName]).Dispose(); 
      HttpContext.Current.Items[ContextName] = null; 
     } 

     if (_dbEntities != null) 
     { 
      _dbEntities.Dispose(); 
      _dbEntities = null; 
     } 
    } 


    public void Dispose() 
    { 
     RemoveContext(); 
    } 

} 

在我的倉庫我使用這樣的數據庫環境:

public class SomeRepository 
{ 
    private static readonly object Lock = new object(); 
    private readonly dbEntities _dbEntities; 

    public SomeRepository() 
    { 
     var databaseContext = new DatabaseContext(); 
     _dbEntities = databaseContext.GetDatabaseContext(); 
    } 


    public IEnumerable<SomeRecord> GetSomeData(int id) 
    { 
     lock (Lock) 
     { 
      return 
       _dbEntities.SomeData.Where(c => c.Id == id); 
     } 
    } 
} 

鎖(鎖)的事情是我瞭解應該幫助這個問題,但在我的情況下,它沒有。通常很難找到描述我的問題的線程,更不用說解決問題了。

該應用程序是一個ASP.NET MVC3應用和它的設置爲9級不同的網站(域確定要被提供給客戶端的內容)中運行的一個應用程序。這9個網站每天的瀏覽量不超過2000次,因此應該在該帳戶上強調數據庫。

我希望有人能幫助並請讓我知道如果有什麼我忘了提。

+0

什麼叫'DatabaseContext.Dispose()'?我使用了類似'HttpContext.Items'設置,並有一個'HttpModule'其在請求結束處置的'ObjectContext'的... – 2012-01-30 20:05:58

+0

其實我覺得'的Dispose()'已自動從'DatabaseContext'實現了一個名爲'IDisposable'。但如果不是,那肯定可以解釋這個錯誤。 我可以在你的'HttpModule'中看看你的代碼嗎? – hylle 2012-01-30 21:29:29

回答

1

按我的意見,Dispose()必須通過在請求結束的東西被調用。你可以像這樣用HttpModule做到這一點:

public class ContextDisposer : IHttpModule 
{ 
    private readonly DatabaseContext _context = new DatabaseContext(); 

    public void Init(HttpApplication context) 
    { 
     context.EndRequest += (sender, e) => this.DisposeContext(sender, e); 
    } 

    private static bool DoesRequestCompletionRequireDisposing(
     string requestPath) 
    { 
     string fileExtension = Path.GetExtension(requestPath) 
      .ToUpperInvariant(); 

     switch (fileExtension) 
     { 
      case ".ASPX": 
      case string.Empty: 
      case null: 
       return true; 
     } 

     return false; 
    } 

    private void DisposeContext(object sender, EventArgs e) 
    { 
     // This gets fired for every request to the server, but there's no 
     // point trying to dispose anything if the request is for (e.g.) a 
     // gif, so only call Dispose() if necessary: 
     string requestedFilePath = ((HttpApplication)sender).Request.FilePath; 

     if (DoesRequestCompletionRequireDisposing(requestedFilePath)) 
     { 
      this._context.Dispose(); 
     } 
    } 
} 

你再插模塊插入這樣的請求管道(你把它變成的System.Web和system.webserver所以它包括了IIS和VS開發網絡服務器):

<system.web> 
    <httpModules> 
     <add name="ContextDisposer" 
      type="MyNamespace.ContextDisposer" /> 
    </httpModules> 
</system.web> 

<system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"> 
     <add name="ContextDisposer" 
      type="MyNamespace.ContextDisposer" /> 
    </modules> 
</system.webServer> 
+0

我發現了一些其他的例子,並在昨天晚上實現了它。實質上,你在這裏寫的是一樣的,你肯定會把我放在正確的道路上。非常感謝! – hylle 2012-01-31 18:40:09

+0

不客氣,很樂意幫忙:) – 2012-01-31 18:47:07

+0

自昨晚以來,我只收到一些關於這個問題的錯誤郵件。這裏是其中的一個: _New交易是不允許的,因爲有在session._ 運行的其他線程和這裏的其他: _The ObjectContext的實例已設置,不能再被用於那些需要connection_ 的操作後者提出了一些懶惰的加載問題,但由於我只收到一個,我認爲這不是太嚴重。 – hylle 2012-01-31 18:47:33

相關問題