c# - session 已关闭对象名称 : 'ISession' . 在 NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() - 如何阻止 session 过早关闭

标签 c# mysql nhibernate fluent-nhibernate ninject

我在带有 MySQL 的 MVC C# 应用程序中使用 NHibernate。我正在尝试让多个用户访问该 session 。我一直在用.InRequestScope()在我的 session 上,但我仍然得到:

System.ObjectDisposedException: Session is closed! Object name: 'ISession'. at NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() *

...或者当我的同事都导航到同一页面同时访问服务时出现 DataReader 错误。

我的 IMasterSessionSource 注入(inject)

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();

内容服务

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();
                };
            }
        }
    }

模型

 public class HomePageContent
    {
        public IEnumerable<Question> Questions { get; set; }
    }

查看

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

但我仍然收到 session 已关闭!错误。如果 session 已关闭,我什至尝试创建一个新的 Kernel.Get,但问题是即使 session 打开,有时也会发生错误。请帮忙!我对这个问题无能为力,而且我似乎无法在任何地方找到解决方案。我几乎认为 NHibernate 不可能一次处理多个 session 。

更新

也许有一种方法可以在打开新 session 之前等待已处理的 session ?

堆栈跟踪

[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.List1..ctor(IEnumerable1 collection) +432 System.Linq.Enumerable.ToList(IEnumerable1 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, IDictionary2 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.WrappedAsyncResultBase1.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.WrappedAsyncResultBase1.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.WrappedAsyncResultBase1.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.WrappedAsyncResultBase1.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.WrappedAsyncResultBase1.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.WrappedAsyncResultBase1.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

最佳答案

我终于明白了。非常感谢@Oskar Berggren 至少热衷于理解我的困境。

问题是,事实上,我一直在共享一个 session 。

这里是我将打开的 session 绑定(bind)到 ContentService 的地方:

 Bind<IContentService>().To<ContentService>().InRequestScope();
        Bind<ISession>()
            .ToMethod(
                context =>
                    context.Kernel.Get<IMasterSessionSource>()
                        .ExposeConfiguration()
                        .BuildSessionFactory()
                        .OpenSession()
            )
            .WhenInjectedInto<IContentService>()
            .InRequestScope(); 

这是我在 ContentService 中调用同一个 session 的地方

 public class ContentService : IContentService
    {
        private readonly ISession _session;

        public ContentService(ISession session)
        {
            _session = session;
        }

        public IQueryable<Question> Questions
        {
            get { return _session.Query<Question>(); }
        }
    }

这就是问题所在。我正在其他地方使用的另一个服务中调用 SAME session

public class DetailsService : IDetailsService
    {
        private readonly IContentService _contentService; //BAD


        public GeneralService(IContentService contentService)
        {
            _contentService = contentService; //BAD
        }

这不是线程安全的,因为一个打开的 session 正在被重用。 每个服务都应该有自己的 session 。

所以我用自己的 session 为 DetailService 创建了绑定(bind),就像这样....

 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,而是将 session 添加到它的 constrictor

    private readonly ISession Session;

    public DetailsService(ISession session)
    {
        Session = session;
    }

然后直接使用 Session.Query() 运行查询;

没有更多的 Session is closed 错误,没有更多的 DataReader 错误,并且最终是一个可以工作的产品。

关于c# - session 已关闭对象名称 : 'ISession' . 在 NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() - 如何阻止 session 过早关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38596986/

相关文章:

c# - 如何防止我的机器人回复 Slack 中的每条消息?

nhibernate - NHibernate Mapping-by-Code 的每个子类继承映射表

nhibernate - 是否有一个 NHibernate 标准实际上什么都不做?

c# - 密码框不会屏蔽我的密码 WPF

C# 单元测试 : UnauthorizedAccessException when using API that uses network

c# - 使用 doxygen 为带有 XML 注释的现有 C# 代码创建文档

php - 尝试对连续的条目重新排序

php - 如何循环重复月份?

mysql - 跨数据库中的表替换列值

c# - 没有 session 绑定(bind)到当前上下文