会话已关闭对象名称:' ISession'。 at NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() - 如何阻止会话过早关闭

时间:2016-07-26 18:06:33

标签: c# mysql nhibernate fluent-nhibernate ninject

我在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.QueryableBase 1.GetEnumerator() +193 System.Collections.Generic.List 1..ctor(IEnumerable 1 collection) +432 System.Linq.Enumerable.ToList(IEnumerable 1 source)+70
  Gcus.PublicGeneralSite.Data.Core.Service.General.DetailsS​​ervice.FindItems(字符串   item,String controller)in   C:\用户\ WD \桌面\主\ Gcus.PublicGeneralSite.Data.Core \服务\一般\ DetailsS​​ervice.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,IDictionary 2 parameters) +603
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
2   参数)+93
  System.Web.Mvc.Async.ActionInvocation.InvokeSynchronousActionMethod()   +97 System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39(IAsyncResult   asyncResult,ActionInvocation innerInvokeState)+53
  System.Web.Mvc.Async.WrappedAsyncResult 2.CallEndDelegate(IAsyncResult asyncResult) +137
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End()+ 187
  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.WrappedAsyncResult 1.CallEndDelegate(IAsyncResult asyncResult) +79
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End()+ 187
  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.WrappedAsyncResult 1.CallEndDelegate(IAsyncResult asyncResult) +75
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End()+176
  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.WrappedAsyncVoid 1.CallEndDelegate(IAsyncResult asyncResult) +135
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End()+176
  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.WrappedAsyncVoid 1.CallEndDelegate(IAsyncResult asyncResult) +98
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End()+176
  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.WrappedAsyncVoid 1.CallEndDelegate(IAsyncResult asyncResult) +135
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End()+176
  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

2 个答案:

答案 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