【问题标题】:Getting error "Session is closed! Object name: 'ISession' while using Castle Windsor使用 Castle Windsor 时出现错误“会话已关闭!对象名称:'ISession'
【发布时间】:2013-01-18 21:32:53
【问题描述】:

是的。这是一个与我如何要求 Castle Windsor 解决我的 ISession 有关的问题,但我已经重读了 5 次代码,但仍然无法弄清楚它有什么问题。

下面是我相当标准的 NHibernate 工具,除了我注册的最后两个组件:

 public class NHibernateFacility : AbstractFacility
    {
        protected override void Init()
        {
            var config = new Configuration().Configure();
            Kernel.Register(
                Component.For<ISessionFactory>()
                    .UsingFactoryMethod((kernel, context) => config.BuildSessionFactory()),
                Component.For<ISession>()
                    .UsingFactoryMethod((kernel, context) => kernel.Resolve<ISessionFactory>().OpenSession())
                    .LifestylePerWebRequest(),
                     Component.For<IStatelessSession>()
                    .UsingFactoryMethod((kernel, context) => kernel.Resolve<ISessionFactory>().OpenStatelessSession())
                    .LifestylePerWebRequest(),
                    Component.For<StatefulSessionWrapper>().LifestylePerWebRequest(),
                    Component.For<StatelessSessionWrapper>().LifestylePerWebRequest()
                );
        }
    }

StatefulSessionWrapper/StatelessSessionWrapper 用作 ISession/IStateless 会话的...包装器,如下所示:

public class StatefulSessionWrapper : ISessionWrapper
    {
        public StatefulSessionWrapper(ISession session)
        {
            this.Session = session;
        }

        private readonly ISession Session;

        #region ISessionWrapper Members

        public ITransaction BeginTransaction()
        {
            return Session.BeginTransaction();
        }

        public ITransaction BeginTransaction(IsolationLevel isolationLevel)
        {
            return Session.BeginTransaction(isolationLevel);
        }

        public ITransaction Transaction { get { return Session.Transaction; } }

        public bool IsConnected
        {
            get { return Session.IsConnected; }
        }

        public bool IsOpen
        {
            get { return Session.IsOpen; }
        }

        #endregion
    }

这样,我可以使用单个动作过滤器,它只处理 NHibernate Session 的事务部分:

public class NHibernateActionFilter<T> : Castle.MonoRail.Framework.IFilter where T:ISessionWrapper
    {
        private readonly T NHibernateSession;

        public NHibernateActionFilter(T session)
        {
            if (session != null)
                NHibernateSession = session;
            else
                throw new NullReferenceException("Session is null");
        }

        #region IFilter Members

        public bool Perform(ExecuteWhen exec, IEngineContext context, IController controller, IControllerContext controllerContext)
        {
            if (exec == ExecuteWhen.BeforeAction)
            {
                NHibernateSession.BeginTransaction();
                return true;
            }
            if (exec == ExecuteWhen.AfterAction)
            {
                if (NHibernateSession.Transaction == null || !NHibernateSession.Transaction.IsActive)
                    return false;
                if (context.LastException != null)
                {
                    NHibernateSession.Transaction.Rollback();
                    return false;
                }
                else
                {
                    NHibernateSession.Transaction.Commit();
                    return true;
                }

            }
            return false;
        }

        #endregion
    }

并像这样简单地使用它:

    [Filter(ExecuteWhen.Always, typeof(NHibernateActionFilter<StatefulSessionWrapper>), ExecutionOrder = 1)]
    [Filter(ExecuteWhen.BeforeAction, typeof(AuthenticationFilter), ExecutionOrder = 2)]
    [Layout("Default"), Rescue("Default")]
    public abstract class NHibernateController : SmartDispatcherController
    {
        public NHibernateController(ISession session)
        {
            this.NHibernateSession = session;
        }

        protected readonly ISession NHibernateSession;
        ..................

唯一的问题?

这是救援页面。请参阅下面的异常详细信息

ObjectDisposedException

消息:会话已关闭!对象名称:'ISession'。

StackTrace:在 NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() 在 p:\nhibernate-core\src\NHibernate\Impl\AbstractSessionImpl.cs:line 207 在 NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus() 在 p:\nhibernate-core\src\NHibernate\Impl\AbstractSessionImpl.cs:第 199 行 在 NHibernate.Impl.SessionImpl.BeginTransaction() 中 p:\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:第 1456 行 ADAutoTotal.Monorail.StatefulSessionWrapper.BeginTransaction() 在 C:\Dropbox\Projects\ADAutoTotal\ADAutoTotal.Monorail\StatefulSessionWrapper.cs:line 23 在 ADAutoTotal.Monorail.NHibernateActionFilter`1.Perform(ExecuteWhen exec,IEngineContext 上下文,IController 控制器, IControllerContext 控制器上下文)在 C:\Dropbox\Projects\ADAutoTotal\ADAutoTotal.Monorail\NHibernateActionFilter.cs:line 31 在 Castle.MonoRail.Framework.Controller.ProcessFilter(ExecuteWhen when, FilterDescriptor desc) 在 C:\Dropbox\Projects\Monorail\castleproject-MonoRail-98c93ac\castleproject-MonoRail-98c93ac\MR2\src\Castle.MonoRail.Framework\Controller.cs:line 2099 at Castle.MonoRail.Framework.Controller.ProcessFilters(IExecutableAction action, ExecuteWhen when) 中 C:\Dropbox\Projects\Monorail\castleproject-MonoRail-98c93ac\castleproject-MonoRail-98c93ac\MR2\src\Castle.MonoRail.Framework\Controller.cs:line 2054 at Castle.MonoRail.Framework.Controller.RunBeforeActionFilters(IExecutableAction 动作,布尔和取消)在 C:\Dropbox\Projects\Monorail\castleproject-MonoRail-98c93ac\castleproject-MonoRail-98c93ac\MR2\src\Castle.MonoRail.Framework\Controller.cs:line 1953 at Castle.MonoRail.Framework.Controller.RunActionAndRenderView() 在 C:\Dropbox\Projects\Monorail\castleproject-MonoRail-98c93ac\castleproject-MonoRail-98c93ac\MR2\src\Castle.MonoRail.Framework\Controller.cs:line 1622

因此,很明显 NHibernateActionFilter 获得了一个关闭会话。但在我看来,不应该。停下来。

【问题讨论】:

  • 对会话管理使用操作过滤器并不是处理事情的最佳方式。
  • 我只在需要使用会话时创建会话并将其包装在事务中。我使用 Windsor 来处理我的 SessionManager。

标签: asp.net-mvc nhibernate castle-windsor


【解决方案1】:

好吧,原来我忘记在我的动作过滤器中添加他们正确的生活方式,因此让温莎让他们单身......

【讨论】:

  • 我在 Ninject 中为 ThreadScope() 设置了一个瞬间。所以下一个线程没有找到会话对象并出错。在@Cosmo 中看到 Singleton 这个词让我印象深刻。
猜你喜欢
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
  • 2020-08-06
  • 2013-08-21
  • 1970-01-01
相关资源
最近更新 更多