我正在使用StructureMap将LINQ数据上下文(DB
类)注入我的存储库,以便在HTTP上下文的基础上进行读取查询,这些查询通过服务层进行查询。一切正常几个小时,直到我收到“Broken”Connection 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语句中。
答案 0 :(得分:3)
看起来你无意中正在创建一个Context的单例:
For<DB>().HttpContextScoped().Use(new DB());
要为每个请求创建新的上下文,请改用:
For<DB>().HttpContextScoped().Use(() => new DB());
答案 1 :(得分:1)
我会为每个存储库使用一个新的DataContext,除非你出于某种原因不能这样做。请参阅此问题:Strange behaviour with StructureMap / ASP.MVC / Visual Studio / LinqToSql
答案 2 :(得分:0)
您的GetUsers方法返回IQueryable,这意味着在迭代某些内容之前,不会从数据库中检索数据。如果返回IQueryable,关闭数据读取器,然后尝试迭代数据,则会出现错误,因为连接已关闭。
答案 3 :(得分:0)
这样做的一个原因是您的连接根本无法打开。正在抑制“SqlConnection.Open”语句中出现的异常。如果问题不在您的应用程序中,则可能是服务器无法授予您连接。可能是因为您的应用程序或同一服务器上托管的某些其他数据库中存在连接泄漏。