2011-03-09 96 views
0

我正在使用StructureMap将LINQ数据上下文(DB类)注入到我的存储库中,以便在基于HTTP上下文的基础上进行读取查询,这些查询通过服务层进行查询。一切正常工作几个小时,直到我得到一个“断开”连接ExecuteReader错误(请参阅下面的完整转储)。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语句中手动包装每个查询。

回答

3

它看起来像你无意创建的背景下的单:

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

为了创建每个请求一个新的背景下,用这个来代替:

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

啊!这就说得通了。我完全错过了lambda表达式的需要。自从我在存储库上实现IDisposable后,我一直没有遇到任何问题。我会等待错误再次发生,并尝试使用它。 – 2011-03-10 12:34:53

1

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

+0

我现在已经从IDisposable基础知识库中调用_db.Dispose()在Dispose上的所有存储库。让我们看看这是否有所作为。 – 2011-03-09 20:56:43

0

你的GetUsers方法返回一个IQueryable,这意味着数据将不会从数据库中检索出来,直到对它进行迭代。如果返回IQueryable,请关闭数据读取器,然后尝试迭代数据,则会出现错误,因为连接已关闭。

+0

我的服务层应该将这些IQueryable压扁以避免这种情况,但这可能是原因。我确实有一些延迟加载,它只映射到Controller中查看模型。这时数据上下文可能会被关闭。为什么它会在导致问题之前的几个小时内正常工作? – 2011-03-09 20:59:18

0

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

相关问题