StructureMapを使用DB
して、リポジトリにLINQデータコンテキスト(クラス)を挿入し、サービスレイヤーを介してクエリされるHTTPコンテキストベースの読み取りクエリを実行しています。「Broken」ConnectionExecuteReaderエラーが発生するまで、数時間はすべて正常に動作します(完全なダンプについては以下を参照してください)。
書き込みクエリ(読み取りクエリではない)はusing (var db = new DB()) {...}
ステートメントにラップされていますが、これが問題の原因になるとは思われません。
MultipleActiveResultSets=true;
しばらくの間問題を解決したように見える接続文字列に追加しましたが、アプリケーションプールをリサイクルするまでエラーが返され、一時的に問題が解決します。おそらく、プールをリサイクルすると、すべての「壊れた」データコンテクストが解放されます。
StructureMapは、HTTPコンテキストごとにデータコンテキストとリポジトリを挿入するように構成されています。
For<DB>().HttpContextScoped().Use(new DB());
For<IUserRepository>().HttpContextScoped().Use<SqlUserRepository>();
データコンテキストは、次のようにユーザーリポジトリによって消費されます。
private DB _db;
public SqlUserRepository(DB db)
{
_db = db;
}
これは、次のようにデータコンテキストを便利にクエリします。
public IQueryable<User> GetUsers()
{
var users = from u in _db.Users
select u; // omitted the rest
}
数時間後、この恐ろしいエラーが発生します。
System.InvalidOperationException: ExecuteReader requires an open and available
Connection. The connection's current state: Broken. at
System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior
runBehavior, Boolean returnStream, String method, DbAsyncResult result) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior
runBehavior, Boolean returnStream, String method) at
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at
System.Data.Common.DbCommand.ExecuteReader() at
System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo,
IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[]
subQueries, Object lastResult) at
System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos,
IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) at
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expressi
on query) at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression
expression) at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source) at
MyApp.Data.SqlUserRepository.GetUser(String username) at
MyApp.Services.BranchService.GetUser(String username) at
MyApp.Controllers.BranchController.get_CurrentUser() at
MyApp.Controllers.BranchController.OnActionExecuting(ActionExecutingContext filterContext)
at
System.Web.Mvc.Controller.System.Web.Mvc.IActionFilter.OnActionExecuting(ActionExecutingCon
text filterContext) at
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter,
ActionExecutingContext preContext, Func`1 continuation) at
System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<>c__DisplayClassf.b__c() at
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext
controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2
parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext
controllerContext, String actionName)
どうすればこれを解決できますか?すべてのクエリをusingステートメントで手動でラップする必要はありません。