2012-01-30 15 views
11

次のエラーの解決方法をお手伝いしたいと願っています。エラーが発生したアプリケーションは本番環境で実行されており、私自身はエラーが発生しません。しかし、1日約20回、エラーメールが届きます。EF4(edmxモデル)を使用しているときに「下層プロバイダがオープンに失敗しました」というエラーが発生する

オープンしているプロバイダが失敗しました。 ---> System.InvalidOperationException:接続が閉じられていません。 接続の現在の状態が接続しています。ここで

スタックトレース

System.Data.EntityExceptionです:オープンに失敗した根本的なプロバイダです。 ---> System.InvalidOperationException:接続が閉じられませんでした。接続の現在の状態は接続中です。 でHibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledConnection.Open() でSystem.Data.ProviderBase.DbConnectionBusy.OpenConnection System.Data.SqlClient.SqlConnection.Open(AT(たDbConnection outerConnection、DbConnectionFactoryはconnectionFactory))でSystem.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(ブール openCondition、たDbConnection storeConnectionToOpen、たDbConnection originalConnection、文字列例外コード、文字列attemptedOperation、 ブール& closeStoreConnectionOnFailure)---内部例外 スタックトレースの終わり--- でSystem.Data .EntityClient.EntityConnection.OpenStoreConnectionIf (ブール openCondition、たDbConnection storeConnectionToOpen、たDbConnection originalConnection、文字列例外コード、ストリングattemptedOperation、 ブール& closeStoreConnectionOnFailure) System.Data.Objects.ObjectContext.EnsureConnectionでSystem.Data.EntityClient.EntityConnection.Open()に()で System.Data.Objects.ELinq.ObjectQueryProvider.b__1 [TResult(IEnumerableを クエリでSystem.Data.Objects.ObjectQuery ソース)で System.Data.Objects.ObjectQuery forMergeOption)式queryRoot)at Sys tem.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute [S](式 式) System.Linq.Queryable.FirstOrDefault [TSOURCE(IQueryable`1源)で
GuideSites.DomainModelで Cで.Repositories.ClinicTermRepository.GetClinicTermByGuideSiteId(のInt32 guideSiteId):プロジェクト\ \ GuideSites \ GuideSites.DomainModel \リポジトリの\ ClinicTermRepository.cs:ライン 20に GuideSites.Web.Frontend.Helpers.VerifyUrlHelper.RedirectOldUrls()でC:\ Projects \ GuideSites \ GuideSites.Web.Frontend \ Helpers \ VerifyUrlHelper.cs:行 91時 GuideSites.Web.Frontend.MvcApplication.Application_BeginRequest(オブジェクト送信者、EventArgs e) C:\ Projects \ GuideSites \ GuideSites.Web.Frontend \ Global.asax.cs:412行 でSystem.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute ) at System.Web.HttpApplication。ExecuteStep(IExecutionStepステップ、 ブール& completedSynchronously)

私はデータベース(MS SQL 2008)に接続する方法は、その結果のHttpContextベースごと要求オブジェクトコンテキストを介してであるEDMXモデルを通じてEF4を使用して、Iデータベースへの接続は、指定されたページロードで必要なすべてのデータに対して開かれたり閉じられたりしません。

私のデータベースのコンテキストクラス以下のようになります。私はこのようなデータベースコンテキストを使用して、私のリポジトリで

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つの異なるWebサイト(ドメインはクライアントに提供されるコンテンツを決定する)として動作する1つのアプリケーションとしてセットアップされます。 9つのウェブサイトには毎日2.000を超えるページビューがありませんので、データベースにそのアカウントを強調する必要があります。

誰かが助けてくれることを願っています。忘れてしまったことがあれば教えてください。

+0

'DatabaseContext.Dispose()'とは何ですか?私は同様の 'HttpContext.Items'設定を使用し、リクエストの最後に' ObjectContext'を破棄する 'HttpModule'を持っています... –

+0

実際に' DatabaseContext'が実装しているので 'Dispose()'が自動的に呼び出されたと思います'IDisposable'。しかし、そうでなければ、間違いを間違いなく説明することができます。 あなたのコードを 'HttpModule'で見ることができますか? – hylle

答えて

1

私のコメントによると、Dispose()はリクエストの最後に何かによって呼び出されなければなりません。あなたはそのようHttpModuleでこれを行うことができます:それはIISとVS devのウェブのために含まれていますので、あなたは、このような要求パイプラインにモジュールを差し込む

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に入れてサーバー):

<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

+0

あなたは歓迎します、喜んで助けてください:) –

+0

私は昨晩以来この問題に関するいくつかのエラーメールを受け取りました。 _セッション中に他のスレッドが実行されているため、新しいトランザクションが許可されません。 そしてもう1つは _ ObjectContextインスタンスは削除されており、接続が必要な操作には使用できません。 後者は怠惰なローディングの問題を示唆していますが、私は1つしか受け取っていないので、あまり重大ではないと思います。 – hylle

関連する問題