Я использую StructureMap для добавления контекста данных LINQ (класс DB
) в мои репозитории для запросов на чтение на основе HTTP-контекста, которые запрашиваются через уровень сервиса. Все работает отлично в течение нескольких часов, пока не получит сообщение «ExecuteReader» «Broken» Connection (полный дамп см. Ниже).
Запросы на запись (не запросы на чтение) заключены в оператор 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)
Как мне это решить? Я действительно не хочу вручную оборачивать каждый запрос в операторе использования.