会话已关闭对象名称:'ISession'。在 NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() - 如何阻止会话过早关闭
Session is closed Object name: 'ISession'. at NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() - How to stop the session from closing prematurely
我在 MySQL 的 MVC C# 应用程序中使用 NHibernate。我正在尝试让多个用户访问该会话。我一直在我的会话中使用 .InRequestScope()
,但我仍然得到:
System.ObjectDisposedException: Session is closed! Object name: 'ISession'. at NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() *
...或者当我让我的同事都导航到同时访问服务的同一页面时出现 DataReader 错误。
我的IMasterSessionSource注入
Bind<IMasterSessionSource>().To<GeneralMasterSessionSource()
.InRequestScope();
我的 IContentService 是我的映射得到服务的地方
//ContentService Bingings
Bind<IContentService>().To<ContentService>().InRequestScope();
Bind<ISession>()
.ToMethod(
context =>
context.Kernel.Get<IMasterSessionSource>()
.ExposeConfiguration()
.BuildSessionFactory()
.OpenSession()
)
.WhenInjectedInto<IContentService>()
.InRequestScope();
ContentService
public interface IContentService
{
IQueryable<Question> Questions{ get; }
}
public class ContentService : IContentService
{
private readonly ISession _session;
public ContentService(ISession session)
{
_session = session;
}
public IQueryable<Question> Questions
{
get { return _session.Query<Question>(); }
}
}
详细服务
public interface IDetailsService
{
IEnumerable<Question> PullQuestions();
}
public class DetailsService : IDetailsService
{
private readonly IContentService _contentService;
public GeneralService(IContentService contentService)
{
_contentService = contentService;
}
public IEnumerable<Question> PullQuestions()
{
var result = _contentService.Questions;
return result;
}
}
控制器
public class Test: Controller
{
private readonly IContentService _contentService;
private readonly IGeneralService _generalService;
public CollegeController(IContentService contentService, IDetailsService detailsService)
{
_contentService = contentService;
_detailsService = detailsService;
}
public ActionResult Index()
{
{
var model = new HomePageContent
{
Questions = _detailsService.PullQuestions().ToList();
};
}
}
}
型号
public class HomePageContent
{
public IEnumerable<Question> Questions { get; set; }
}
VIEW
foreach(var question in Model.Questions){
@Html.Raw(question.Question)
}
因此对于访问该页面的单个用户。一切正常。但是当多个用户访问同一页面时,每个用户都会收到错误:
{"There is already an open DataReader associated with this Connection which must be closed first."}
{"There is already an open DataReader associated with this Connection which must be closed first."}
{"No current query in data reader"}
{"No current query in data reader"}
{"There is already an open DataReader associated with this Connection which must be closed first."}
{"Session is closed!\r\nObject name: 'ISession'."}
我已经添加了 InRequestScope。我什至添加了这个实现:
NHibernate, and odd "Session is Closed!" errors
但我仍然收到会话已关闭!错误。如果会话已关闭,我什至尝试创建一个新的 Kernel.Get,但问题是即使会话打开,有时也会出现错误。请帮忙!我对这个问题无能为力,而且我似乎无法在任何地方找到解决方案。我几乎认为 NHibernate 不可能一次处理多个会话。
更新
也许有一种方法可以在打开新会话之前等待已处理的会话?
堆栈跟踪
[ObjectDisposedException: Session is closed! Object name: 'ISession'.]
NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() +192
NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus() +55
NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression
queryExpression) +171
NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression
expression, IQuery& query, NhLinqExpression& nhQuery) +226
NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
+80 NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +74 Remotion.Linq.QueryableBase1.GetEnumerator() +193
System.Collections.Generic.List
1..ctor(IEnumerable1 collection) +432
System.Linq.Enumerable.ToList(IEnumerable
1 source) +70
Gcus.PublicGeneralSite.Data.Core.Service.General.DetailsService.FindItems(String
item, String controller) in
c:\Users\wd\Desktop\master\Gcus.PublicGeneralSite.Data.Core\Service\General\DetailsService.cs:724
Gcus.Com.Web.Controllers.CoursesController.Details(String category,
String item) in
c:\Users\wd\Desktop\master\Gcus.Com.Web\Controllers\CoursesController.cs:213
lambda_method(Closure , ControllerBase , Object[] ) +366
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase
controller, Object[] parameters) +87
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext
controllerContext, IDictionary2 parameters) +603<br>
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext
controllerContext, ActionDescriptor actionDescriptor, IDictionary
2
parameters) +93
System.Web.Mvc.Async.ActionInvocation.InvokeSynchronousActionMethod()
+97 System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39(IAsyncResult
asyncResult, ActionInvocation innerInvokeState) +53
System.Web.Mvc.Async.WrappedAsyncResult2.CallEndDelegate(IAsyncResult
asyncResult) +137<br>
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +187
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +136
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult
asyncResult) +76
System.Web.Mvc.Async.AsyncInvocationWithFilters.b__3d()
+164 System.Web.Mvc.Async.<>c__DisplayClass46.b__3f()
+549 System.Web.Mvc.Async.<>c__DisplayClass33.b__32(IAsyncResult asyncResult) +75
System.Web.Mvc.Async.WrappedAsyncResult1.CallEndDelegate(IAsyncResult
asyncResult) +79<br>
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +187
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +136
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult
asyncResult) +76
System.Web.Mvc.Async.<>c__DisplayClass2b.b__1c()
+114 System.Web.Mvc.Async.<>c__DisplayClass21.b__1e(IAsyncResult
asyncResult) +306
System.Web.Mvc.Async.WrappedAsyncResult1.CallEndDelegate(IAsyncResult
asyncResult) +75<br>
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +72
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult
asyncResult) +60
System.Web.Mvc.Controller.b__1d(IAsyncResult
asyncResult, ExecuteCoreState innerState) +70
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult
asyncResult) +135<br>
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +51
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +66
System.Web.Mvc.Controller.b__15(IAsyncResult
asyncResult, Controller controller) +60
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult
asyncResult) +98<br>
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +51 System.Web.Mvc.Controller.EndExecute(IAsyncResult
asyncResult) +60
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult
asyncResult) +60
System.Web.Mvc.MvcHandler.b__5(IAsyncResult
asyncResult, ProcessRequestState innerState) +70
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult
asyncResult) +135<br>
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
Object tag) +51
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
+60 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult
result) +59
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+399 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +137
我不熟悉 ninject,我怀疑它与这里的问题有关。
如果您不知道如何正确处理会话,您可以看看 NHibernate 自己对上下文会话的处理:http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-current-session
我终于明白了。非常感谢@Oskar Berggren 至少热衷于理解我的困境。
问题是我实际上一直在共享一个会话。
这里是我将打开的会话绑定到 ContentService 的地方:
Bind<IContentService>().To<ContentService>().InRequestScope();
Bind<ISession>()
.ToMethod(
context =>
context.Kernel.Get<IMasterSessionSource>()
.ExposeConfiguration()
.BuildSessionFactory()
.OpenSession()
)
.WhenInjectedInto<IContentService>()
.InRequestScope();
这是我在 ContentService 中调用同一个会话的地方
public class ContentService : IContentService
{
private readonly ISession _session;
public ContentService(ISession session)
{
_session = session;
}
public IQueryable<Question> Questions
{
get { return _session.Query<Question>(); }
}
}
问题就出在这里。我正在其他地方使用的另一个服务中调用 SAME 会话
public class DetailsService : IDetailsService
{
private readonly IContentService _contentService; //BAD
public GeneralService(IContentService contentService)
{
_contentService = contentService; //BAD
}
这不是线程安全的,因为一个打开的会话正在被重用。 每个服务都应该有自己的会话。
所以我用自己的会话为 DetailService 创建了绑定,就像这样....
Bind<IDetailsService>()
.To<DetailsService>()
.InRequestScope();
Bind<ISession>()
.ToMethod(
context =>
{
var lockObject = new object();
lock (lockObject)
{
return context.Kernel.Get<IMasterSessionSource>()
.ExposeConfiguration()
.BuildSessionFactory()
.OpenSession();
}
}
)
.WhenInjectedInto<IDetailsService>()
.InRequestScope();
我没有在该服务中调用 _contentService,而是将会话添加到它的 constrictor
private readonly ISession Session;
public DetailsService(ISession session)
{
Session = session;
}
然后 运行 直接使用 Session.Query();
查询
不再有 Session is closed 错误,不再有 DataReader 错误,最终是一个可以工作的产品。
我在 MySQL 的 MVC C# 应用程序中使用 NHibernate。我正在尝试让多个用户访问该会话。我一直在我的会话中使用 .InRequestScope()
,但我仍然得到:
System.ObjectDisposedException: Session is closed! Object name: 'ISession'. at NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() *
...或者当我让我的同事都导航到同时访问服务的同一页面时出现 DataReader 错误。
我的IMasterSessionSource注入
Bind<IMasterSessionSource>().To<GeneralMasterSessionSource()
.InRequestScope();
我的 IContentService 是我的映射得到服务的地方
//ContentService Bingings
Bind<IContentService>().To<ContentService>().InRequestScope();
Bind<ISession>()
.ToMethod(
context =>
context.Kernel.Get<IMasterSessionSource>()
.ExposeConfiguration()
.BuildSessionFactory()
.OpenSession()
)
.WhenInjectedInto<IContentService>()
.InRequestScope();
ContentService
public interface IContentService
{
IQueryable<Question> Questions{ get; }
}
public class ContentService : IContentService
{
private readonly ISession _session;
public ContentService(ISession session)
{
_session = session;
}
public IQueryable<Question> Questions
{
get { return _session.Query<Question>(); }
}
}
详细服务
public interface IDetailsService
{
IEnumerable<Question> PullQuestions();
}
public class DetailsService : IDetailsService
{
private readonly IContentService _contentService;
public GeneralService(IContentService contentService)
{
_contentService = contentService;
}
public IEnumerable<Question> PullQuestions()
{
var result = _contentService.Questions;
return result;
}
}
控制器
public class Test: Controller
{
private readonly IContentService _contentService;
private readonly IGeneralService _generalService;
public CollegeController(IContentService contentService, IDetailsService detailsService)
{
_contentService = contentService;
_detailsService = detailsService;
}
public ActionResult Index()
{
{
var model = new HomePageContent
{
Questions = _detailsService.PullQuestions().ToList();
};
}
}
}
型号
public class HomePageContent
{
public IEnumerable<Question> Questions { get; set; }
}
VIEW
foreach(var question in Model.Questions){
@Html.Raw(question.Question)
}
因此对于访问该页面的单个用户。一切正常。但是当多个用户访问同一页面时,每个用户都会收到错误:
{"There is already an open DataReader associated with this Connection which must be closed first."} {"There is already an open DataReader associated with this Connection which must be closed first."} {"No current query in data reader"} {"No current query in data reader"} {"There is already an open DataReader associated with this Connection which must be closed first."} {"Session is closed!\r\nObject name: 'ISession'."}
我已经添加了 InRequestScope。我什至添加了这个实现: NHibernate, and odd "Session is Closed!" errors
但我仍然收到会话已关闭!错误。如果会话已关闭,我什至尝试创建一个新的 Kernel.Get,但问题是即使会话打开,有时也会出现错误。请帮忙!我对这个问题无能为力,而且我似乎无法在任何地方找到解决方案。我几乎认为 NHibernate 不可能一次处理多个会话。
更新
也许有一种方法可以在打开新会话之前等待已处理的会话?
堆栈跟踪
[ObjectDisposedException: Session is closed! Object name: 'ISession'.] NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() +192
NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus() +55 NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression) +171
NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery) +226
NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +80 NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +74 Remotion.Linq.QueryableBase1.GetEnumerator() +193 System.Collections.Generic.List
1..ctor(IEnumerable1 collection) +432 System.Linq.Enumerable.ToList(IEnumerable
1 source) +70
Gcus.PublicGeneralSite.Data.Core.Service.General.DetailsService.FindItems(String item, String controller) in c:\Users\wd\Desktop\master\Gcus.PublicGeneralSite.Data.Core\Service\General\DetailsService.cs:724 Gcus.Com.Web.Controllers.CoursesController.Details(String category, String item) in c:\Users\wd\Desktop\master\Gcus.Com.Web\Controllers\CoursesController.cs:213 lambda_method(Closure , ControllerBase , Object[] ) +366
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +87
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +603<br> System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
2 parameters) +93
System.Web.Mvc.Async.ActionInvocation.InvokeSynchronousActionMethod() +97 System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +53
System.Web.Mvc.Async.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult) +137<br> System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +187
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +136
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +76
System.Web.Mvc.Async.AsyncInvocationWithFilters.b__3d() +164 System.Web.Mvc.Async.<>c__DisplayClass46.b__3f() +549 System.Web.Mvc.Async.<>c__DisplayClass33.b__32(IAsyncResult asyncResult) +75
System.Web.Mvc.Async.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) +79<br> System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +187
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +136
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +76
System.Web.Mvc.Async.<>c__DisplayClass2b.b__1c() +114 System.Web.Mvc.Async.<>c__DisplayClass21.b__1e(IAsyncResult asyncResult) +306
System.Web.Mvc.Async.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) +75<br> System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +60
System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +70
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +135<br> System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +51
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +66 System.Web.Mvc.Controller.b__15(IAsyncResult asyncResult, Controller controller) +60
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +98<br> System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +51 System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +60
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +70
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +135<br> System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +51
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +59
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +399 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +137
我不熟悉 ninject,我怀疑它与这里的问题有关。
如果您不知道如何正确处理会话,您可以看看 NHibernate 自己对上下文会话的处理:http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-current-session
我终于明白了。非常感谢@Oskar Berggren 至少热衷于理解我的困境。
问题是我实际上一直在共享一个会话。
这里是我将打开的会话绑定到 ContentService 的地方:
Bind<IContentService>().To<ContentService>().InRequestScope();
Bind<ISession>()
.ToMethod(
context =>
context.Kernel.Get<IMasterSessionSource>()
.ExposeConfiguration()
.BuildSessionFactory()
.OpenSession()
)
.WhenInjectedInto<IContentService>()
.InRequestScope();
这是我在 ContentService 中调用同一个会话的地方
public class ContentService : IContentService
{
private readonly ISession _session;
public ContentService(ISession session)
{
_session = session;
}
public IQueryable<Question> Questions
{
get { return _session.Query<Question>(); }
}
}
问题就出在这里。我正在其他地方使用的另一个服务中调用 SAME 会话
public class DetailsService : IDetailsService
{
private readonly IContentService _contentService; //BAD
public GeneralService(IContentService contentService)
{
_contentService = contentService; //BAD
}
这不是线程安全的,因为一个打开的会话正在被重用。 每个服务都应该有自己的会话。
所以我用自己的会话为 DetailService 创建了绑定,就像这样....
Bind<IDetailsService>()
.To<DetailsService>()
.InRequestScope();
Bind<ISession>()
.ToMethod(
context =>
{
var lockObject = new object();
lock (lockObject)
{
return context.Kernel.Get<IMasterSessionSource>()
.ExposeConfiguration()
.BuildSessionFactory()
.OpenSession();
}
}
)
.WhenInjectedInto<IDetailsService>()
.InRequestScope();
我没有在该服务中调用 _contentService,而是将会话添加到它的 constrictor
private readonly ISession Session;
public DetailsService(ISession session)
{
Session = session;
}
然后 运行 直接使用 Session.Query();
查询不再有 Session is closed 错误,不再有 DataReader 错误,最终是一个可以工作的产品。