2012-01-30 33 views
11

Tôi hy vọng ai đó có thể giúp tôi giải quyết lỗi sau. Ứng dụng trong đó lỗi xảy ra đang chạy trong sản xuất và tôi không bao giờ tự mình gặp phải lỗi. Tuy nhiên, khoảng 20 lần mỗi ngày, tôi nhận được một thông báo lỗi cho tôi biết:Thỉnh thoảng lỗi "Nhà cung cấp cơ sở không thành công khi mở" khi sử dụng EF4 (mô hình edmx)

Nhà cung cấp cơ sở không thành công khi mở. ---> System.InvalidOperationException: Kết nối không được đóng. Trạng thái hiện tại của kết nối đang kết nối.

Dưới đây là stack trace

System.Data.EntityException: Nhà cung cấp cơ bản đã thất bại vào Open. ---> System.InvalidOperationException: Kết nối không được đóng. Trạng thái hiện tại của kết nối đang kết nối. tại System.Data.ProviderBase.DbConnectionBusy.OpenConnection (DbConnection outerConnection, DbConnectionFactory ConnectionFactory) tại System.Data.SqlClient.SqlConnection.Open() tại HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledConnection.Open() tại System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf (Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, string exceptionCode, string attemptedOperation, Boolean & closeStoreConnectionOnFailure) --- End của nội ngoại lệ stack trace --- tại System.Data .EntityClient.EntityConnection.OpenStoreConnectionNếu (Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean & closeStoreConnectionOnFailure) tại System.Data.EntityClient.EntityConnection.Open() tại System.Data.Objects.ObjectContext.EnsureConnection() tại System.Data.Objects.ObjectQuery forMergeOption) tại System.Data.Objects.ObjectQuery nguồn) tại System.Data.Objects.ELinq.ObjectQueryProvider.b__1 [TResult] (IEnumerable truy vấn, Expression queryRoot) tại Sys tem.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute [S] (Biểu expression) tại System.Linq.Queryable.FirstOrDefault [TSource] (nguồn IQueryable`1)
tại GuideSites.DomainModel .Repositories.ClinicTermRepository.GetClinicTermByGuideSiteId (Int32 guideSiteId) trong C: \ Projects \ GuideSites \ GuideSites.DomainModel \ Repositories \ ClinicTermRepository.cs: dòng 20 tại GuideSites.Web.Frontend.Helpers.VerifyUrlHelper.RedirectOldUrls() trong C: \ Projects \ GuideSites \ GuideSites.Web.Frontend \ Helpers \ VerifyUrlHelper.cs: dòng 91 tại GuideSites.Web.Frontend.MvcApplication.Application_BeginRequest (Object người gửi, EventArgs e) trong C: \ Projects \ GuideSites \ GuideSites.Web.Frontend \ Global.asax.cs: dòng 412 tại System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute () tại System.Web.HttpApplication.ExecuteStep (IExecutionStep bước, Boolean & completedSynchronously)

tôi sử dụng EF4 thông qua một mô hình EDMX và tôi đường tôi kết nối với cơ sở dữ liệu (MS SQL 2008) là thông qua một HttpContext dựa trên mỗi yêu cầu đối tượng bối cảnh như vậy mà các kết nối đến cơ sở dữ liệu không được mở và đóng cho mỗi phần dữ liệu tôi cần trên một lần tải trang nhất định.

My lớp Cơ sở dữ liệu bối cảnh trông như thế này:

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(); 
    } 

} 

Trong kho của tôi, tôi sử dụng bối cảnh cơ sở dữ liệu như thế này:

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); 
     } 
    } 
} 

Các khóa (Lock) điều là cái gì tôi đọc về nên giúp vấn đề này nhưng trong trường hợp của tôi thì không. Và nói chung, thật khó để tìm ra các chủ đề mô tả chính xác vấn đề của tôi, hãy để một mình giải pháp cho vấn đề.

Ứng dụng này là một ứng dụng ASP.NET MVC3 và nó được thiết lập như một ứng dụng đang chạy cho 9 trang web khác nhau (miền xác định nội dung sẽ được phục vụ cho khách hàng). 9 trang web không có hơn 2.000 lượt xem trang hàng ngày, do đó, cơ sở dữ liệu cần được nhấn mạnh trên tài khoản đó.

Tôi hy vọng ai đó có thể giúp đỡ và vui lòng cho tôi biết nếu có điều gì đó tôi quên đề cập đến.

+0

Cuộc gọi nào 'DatabaseContext.Dispose()'? Tôi sử dụng một thiết lập 'HttpContext.Items' tương tự và có' HttpModule' để xử lý 'ObjectContext' ở cuối yêu cầu ... –

+0

Thực ra tôi đã nghĩ rằng' Dispose() 'được gọi tự động từ các thực thi' DatabaseContext' 'IDisposable'. Nhưng nếu không, điều đó chắc chắn có thể giải thích được lỗi. Tôi có thể xem mã của bạn trong 'HttpModule' của bạn không? – hylle

Trả lời

1

Theo nhận xét của tôi, Dispose() phải được gọi bằng thứ gì đó ở cuối yêu cầu. Bạn có thể làm điều này với một HttpModule như vậy:

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(); 
     } 
    } 
} 

bạn sau đó cắm các module vào các đường ống dẫn yêu cầu như thế này (bạn đặt nó vào system.web và system.webServer vì vậy nó bao gồm cho IIS và các dev web VS máy chủ):

<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

Tôi tìm thấy một số ví dụ khác và thực hiện nó đêm qua. Về bản chất nó giống như bạn đã viết ở đây và bạn chắc chắn đặt tôi vào con đường bên phải. Cảm ơn rất nhiều! – hylle

+0

Bạn được chào đón, vui lòng trợ giúp :) –

+0

Tôi đã nhận được một vài thư lỗi liên quan đến vấn đề này kể từ đêm qua. Đây là một trong số họ: _Không được phép giao dịch mới vì có các chủ đề khác đang chạy trong phiên._ Và đây là một chủ đề khác: _Đối tượng ObjectContext đã được xử lý và không thể sử dụng cho các hoạt động yêu cầu kết nối_ sau đó cho thấy một số vấn đề tải chậm nhưng kể từ khi tôi chỉ nhận được một, tôi không nghĩ rằng nó quá nghiêm trọng. – hylle

Các vấn đề liên quan