ExecuteReader требует открытого соединения. Текущее состояние: сломан - PullRequest
0 голосов
/ 09 марта 2011

Я использую 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)

Как мне это решить? Я действительно не хочу вручную оборачивать каждый запрос в операторе использования.

Ответы [ 4 ]

3 голосов
/ 10 марта 2011

Похоже, что вы непреднамеренно создаете единственный контекст:

For<DB>().HttpContextScoped().Use(new DB());

Чтобы создать новый контекст для запроса, используйте вместо этого:

For<DB>().HttpContextScoped().Use(() => new DB());
1 голос
/ 09 марта 2011

Я бы просто использовал новый DataContext для каждого репозитория, если вы не можете по какой-либо причине.Смотрите этот вопрос: Странное поведение с StructureMap / ASP.MVC / Visual Studio / LinqToSql

0 голосов
/ 21 декабря 2011

Одной из причин этого может быть то, что ваше соединение вообще не может быть открыто.Любое исключение, которое появляется в операторе "SqlConnection.Open", подавляется.Если проблема не в вашем приложении, возможно, сервер не может предоставить вам соединение.Может быть из-за утечки соединения в вашем приложении или в другой базе данных, размещенной на том же сервере.

0 голосов
/ 09 марта 2011

Ваш метод GetUsers возвращает IQueryable, что означает, что данные не будут извлечены из базы данных, пока что-то не пройдет по ней.Если вы вернете IQueryable, закроете устройство чтения данных, а затем попытаетесь выполнить итерацию по данным, вы получите ошибку, поскольку соединение закрыто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...