我在MySQL的MVC C#应用程序中使用NHibernate。我想让多个用户访问会话。我一直在我的会话中使用.InRequestScope()
,但我仍然得到:
当我让我的同事全部导航到同时访问服务的同一页面时,System.ObjectDisposedException:会话已关闭!对象名称:' ISession'。在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;
}
}
CONTROLLER
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();
};
}
}
}
MODEL
public class HomePageContent
{
public IEnumerable<Question> Questions { get; set; }
}
查看
foreach(var question in Model.Questions){
@Html.Raw(question.Question)
}
因此,对于访问该页面的单个用户。一切正常。但是当mutliple用户访问同一页面时,每个人都会得到错误:
{&#34;已经有一个与此Connection关联的开放DataReader必须先关闭。&#34;} {&#34;已经有一个与此Connection关联的开放DataReader必须先关闭。&#34;} {&#34;数据阅读器中没有当前查询&#34;} {&#34;数据阅读器中没有当前查询&#34;} {&#34;已经有一个与此Connection关联的开放DataReader必须先关闭。&#34;} {&#34;会话已关闭!\ r \ n对象名称:&#39; ISession&#39;。&#34;}
我已经添加了InRequestScope。我甚至添加了这个实现: NHibernate, and odd "Session is Closed!" errors
但我仍然关闭Sessions!错误。我甚至尝试创建一个新的Kernel.Get如果会话已关闭,但问题是即使会话打开时有时也会发生错误。请帮忙!我对这个问题很有见,我似乎无法在任何地方找到解决方案。我几乎认为NHibernate不可能同时处理多个会话。
更新
也许有一种方法可以在开启新节目之前等待已处理的会话?
堆栈跟踪
[ObjectDisposedException:会话已关闭!对象名称:&#39; ISession&#39;。] NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed()+192
NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus()+55 NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)+171
NHibernate.Linq.DefaultQueryProvider.PrepareQuery(表达式 表达,IQuery&amp;查询,NhLinqExpression&amp; nhQuery)+226
NHibernate.Linq.DefaultQueryProvider.Execute(表达式表达式) +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(字符串 item,String controller)in C:\用户\ WD \桌面\主\ Gcus.PublicGeneralSite.Data.Core \服务\一般\ DetailsService.cs:724 Gcus.Com.Web.Controllers.CoursesController.Details(String category, 字符串项) C:\ Users \用户WD \桌面\主\ Gcus.Com.Web \控制器\ CoursesController.cs:213 lambda_method(Closure,ControllerBase,Object [])+366
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller,Object []参数)+87
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext,IDictionary2 parameters) +603
2 参数)+93
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
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
1.End()+ 187
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+136
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult的 asyncResult)+76
System.Web.Mvc.Async.AsyncInvocationWithFilters.b__3d() +164 System.Web.Mvc.Async。&lt;&gt; c__DisplayClass46.b__3f() +549 System.Web.Mvc.Async。&lt;&gt; c__DisplayClass33.b__32(IAsyncResult asyncResult)+75
System.Web.Mvc.Async.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) +79
1.End()+ 187
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+136
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult的 asyncResult)+76
System.Web.Mvc.Async&LT;&GT; c__DisplayClass2b.b__1c() +114 System.Web.Mvc.Async。&lt;&gt; c__DisplayClass21.b__1e(IAsyncResult) asyncResult)+306
System.Web.Mvc.Async.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) +75
1.End()+176
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+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
1.End()+176
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+51
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)+66 System.Web.Mvc.Controller.b__15(IAsyncResult的 asyncResult,控制器控制器)+60
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +98
1.End()+176
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+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
1.End()+176
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, 对象标签)+51
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult) 结果)+59
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +399 System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean&amp; completedSynchronously)+137
答案 0 :(得分:2)
我终于明白了。非常感谢@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,而是将会话添加到其缩写器
private readonly ISession Session;
public DetailsService(ISession session)
{
Session = session;
}
然后直接使用Session.Query();
运行查询没有更多的会话是关闭错误,没有更多DataReader错误,最后是工作产品。
答案 1 :(得分:0)
我不熟悉ninject,我怀疑这里涉及到这个问题。
如果你无法弄清楚如何正确处理会话,你可以看看NHibernate自己对上下文会话的处理:http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-current-session