ExecuteReader 需要打开连接。当前状态:破碎

Posted

技术标签:

【中文标题】ExecuteReader 需要打开连接。当前状态:破碎【英文标题】:ExecuteReader requires open Connection. Current state: Broken 【发布时间】:2011-03-09 16:02:54 【问题描述】:

我正在使用 StructureMap 将 LINQ 数据上下文(DB 类)注入到我的存储库中,用于基于 HTTP 上下文的读取查询,这些查询通过服务层进行查询。几个小时内一切正常,直到我收到“Broken”连接 ExecuteReader 错误(完整转储见下文)。

写入查询(不是读取查询)包含在 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 语句中。

【问题讨论】:

【参考方案1】:

您似乎无意中创建了 Context 的单例:

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

为了为每个请求创建一个新的上下文,请改用这个:

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

【讨论】:

啊!这就说得通了。我完全错过了对 lambda 表达式的需求。自从我在我的存储库上实现 IDisposable 以来,我没有遇到任何问题。我将等待错误再次出现并尝试此操作。【参考方案2】:

我只会为每个存储库使用一个新的 DataContext ,除非由于某种原因你不能这样做。看到这个问题:Strange behaviour with StructureMap / ASP.MVC / Visual Studio / LinqToSql

【讨论】:

我现在已经从 IDisposable 基础存储库派生了所有存储库,该存储库在 Dispose 上调用 _db.Dispose()。让我们看看这是否会有所不同。【参考方案3】:

您的 GetUsers 方法正在返回一个 IQueryable,这意味着数据不会从数据库中检索到,直到有东西对其进行迭代。如果返回 IQueryable,关闭数据读取器,然后尝试遍历数据,则会收到错误消息,因为连接已关闭。

【讨论】:

我的服务层应该展平这些 IQueryables 以避免这种情况,但这可能是原因。我确实有一些延迟加载,它只映射到控制器中的视图模型。此时数据上下文可能已关闭。为什么它会在引起问题之前正常工作几个小时?【参考方案4】:

其中一个原因是您的连接根本无法打开。 “SqlConnection.Open”语句中出现的任何异常都被抑制了。如果问题不在您的应用程序中,则可能是服务器无法授予您连接。可能是因为您的应用或托管在同一服务器上的其他数据库中的连接泄漏。

【讨论】:

以上是关于ExecuteReader 需要打开连接。当前状态:破碎的主要内容,如果未能解决你的问题,请参考以下文章

System.InvalidOperationException:ExecuteReader 需要打开且可用的连接。连接的当前状态为关闭

ExecuteReader 需要一个开放且可用的连接。连接的当前状态是 Connecting

ExecuteReader 要求已打开且可用的连接。连接的当前状态为已关闭。

ExecuteReader 需要一个开放且可用的连接 Asp.net

ExecuteReader 需要打开的连接

无法连接到远程 MS Access 数据库