Asp.net mvc 刷新页面时,NHibernate会话关闭

Asp.net mvc 刷新页面时,NHibernate会话关闭,asp.net-mvc,asp.net-mvc-4,session,nhibernate,Asp.net Mvc,Asp.net Mvc 4,Session,Nhibernate,这是我这几天遇到的另一个奇怪的问题!!!我已经使用nhibernate创建和安装了MVC4应用程序。并在my HomeController上添加了名为[LoggingNHibernateSessionAttribute]的筛选器属性,该属性管理每个操作的会话。我关注了“ASP.NETMVC4和Apress发布的Web API” public class LoggingNHibernateSessionAttribute : ActionFilterAttribute { private

这是我这几天遇到的另一个奇怪的问题!!!我已经使用nhibernate创建和安装了MVC4应用程序。并在my HomeController上添加了名为[LoggingNHibernateSessionAttribute]的筛选器属性,该属性管理每个操作的会话。我关注了“ASP.NETMVC4和Apress发布的Web API”

public class LoggingNHibernateSessionAttribute : ActionFilterAttribute
{
    private readonly IActionLogHelper _actionLogHelper;
    private readonly IActionExceptionHandler _actionExceptionHandler;
    private readonly IActionTransactionHelper _actionTransactionHelper;

    public LoggingNHibernateSessionAttribute()
        : this(WebContainerManager.Get<IActionLogHelper>(),
        WebContainerManager.Get<IActionExceptionHandler>(),
        WebContainerManager.Get<IActionTransactionHelper>())
    {
    }

    public LoggingNHibernateSessionAttribute(
        IActionLogHelper actionLogHelper,
        IActionExceptionHandler actionExceptionHandler,
        IActionTransactionHelper actionTransactionHelper)
    {
        _actionLogHelper = actionLogHelper;
        _actionExceptionHandler = actionExceptionHandler;
        _actionTransactionHelper = actionTransactionHelper;
    }

    public override void OnActionExecuting(ActionExecutingContext actionExectingContext)
    {
        _actionLogHelper.LogEntry(actionExectingContext.ActionDescriptor);
        _actionTransactionHelper.BeginTransaction();
    }

    public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
    {
        _actionTransactionHelper.EndTransaction(actionExecutedContext);
        _actionTransactionHelper.CloseSession();
        _actionExceptionHandler.HandleException(actionExecutedContext);
        _actionLogHelper.LogExit(actionExecutedContext.ActionDescriptor);
    }
}
运行应用程序时,我可以在数据库中保存一个实体。但当我点击刷新按钮并抛出异常时,表示会话已关闭

我不知道为什么会这样。(我搜索并找到了这个,但无法解决我的问题)

在我的NinjectConfigurator中,我将inRequestScope()添加到了所有注入中,但没有得到响应。我在刷新页面时已选中,将打开该页面会话。但我不知道为什么说会议结束了

更新:

当我第一次运行应用程序时。我可以创建一个新成员。但当我点击刷新按钮时,会话将意外关闭!! 首次运行:

  • 一切正常
  • 点击刷新按钮后:

  • 新会话绑定到当前上下文
  • 新会话将被注入存储库(会话已打开)
  • ActionTransactionHelper调用beginTransaction() 4-调用customMembership createUser(..) 5-但是当存储库会话中调用的_userRepositoy.save(user)关闭时 注意:但当仍然未调用endTransaction和closeSession时。但会议是如何结束的? 如果我在onActionExecute()中注释closeSession()。会话始终处于打开状态,如果刷新页面,一切正常。 我检查了很多,尝试了不同的方法。只有当我第二次想使用customMembership执行CRUD操作时,才会发生这种情况

    对于其他实体,它就像一个符咒! 我已经上传了我的示例代码。对于测试,只需创建并清空数据库并更改连接字符串。然后转到localHost:*****/api/categories(不需要用户和密码)

    下载示例项目: 大小:47MB

    大小:54MB
    Zip格式:

    这里一个非常重要的事情,可能是NHibernate的性质。NHibernate及其
    会话
    在ASP.NET MVC中的寿命更长,这是可以预料的。我的意思是不仅仅是在

    • 动作执行(控制器动作开始)
    • ActionExecuted(调用视图或重定向)
    实际上,会话还必须经历渲染阶段。因为,我们可以在“Action()”中加载一些代理,但它的集合只能在
    视图
    呈现期间延迟加载。因此,即使在这些阶段,也必须打开
    会话
    (从请求开始的同一个会话)

    • ResultExecuting(只能在此处开始加载代理)
    • ResultExecuted(几乎全部完成,让我们关闭会话)
    换句话说在整个请求过程中保持会话打开。从授权到呈现内容

    注意:另一个提示,为了确保一切正常,我正在使用这个场景(也许您也这样做):

  • 客户端窗体将要将数据发送到服务器。方法是POST,操作是Update()
  • 发送表单到服务器,触发Action Update()-所有事务都已就绪(如上所述)
  • 一旦NHibernate将数据持久化到数据库中,Update()操作将结束,并重定向到操作
    • Detail()
      如果一切正常或
    • Edit()
      如果出现问题
  • 用户浏览器已重定向到“操作详细信息”或“编辑”。因此,如果用户刷新,则会刷新细节或编辑。根本不调用
    Update()
    (这是一个POST方法)

  • 事实上,这是第一步。是操作
    详细信息
    编辑
    之一。在这种情况下,我们已经面临这个问题了…

    您有这个错误,因为Asp.Net MVC不会为每个请求创建一个新的
    LoggingHbernateSessionAttribute实例。它会在您第一次请求操作时创建一个新实例,然后在将来使用这个实例

    其行为如下:

  • 第一次调用
    Post
    ->“LoggingNHibernateSession”的新实例已创建
  • 第一次调用
    Put
    ->创建另一个“LoggingNHibernateSession”实例
  • 第二次调用上一步中的“LoggingNHibernateSession”实例
  • 第一次调用
    Delete
    ->创建另一个“LoggingNHibernateSession”实例

    [LoggingNHibernateSession]
    public JsonResult Post(Dto data)
    {
        /* ... */
    }
    
    [LoggingNHibernateSession]
    public JsonResult Put(int id, Dto data)
    {
        /* ... */
    }
    
    [LoggingNHibernateSession]
    public JsonResult Delete(int id)
    {
        /* ... */
    } 
    
  • 可以使用
    Func
    而不是构造函数中的
    IActionLogHelper
    来解决此问题。
    可以在
    OnActionExecuting
    方法中初始化
    IActionLogHelper
    的实例

    public class LoggingNHibernateSessionAttribute : ActionFilterAttribute
    {
        /* your code */
        private readonly Func<IActionTransactionHelper> _getActionTransactionHelper;
        private IActionTransactionHelper _actionTransactionHelper;
    
        public LoggingNHibernateSessionAttribute()
            : this(WebContainerManager.Get<IActionLogHelper>(),
            WebContainerManager.Get<IActionExceptionHandler>(),
            () => WebContainerManager.Get<IActionTransactionHelper>())
        {
        }
    
        public LoggingNHibernateSessionAttribute(
            IActionLogHelper actionLogHelper,
            IActionExceptionHandler actionExceptionHandler,
            Func<IActionTransactionHelper> getActionTransactionHelper)
        {
            _actionLogHelper = actionLogHelper;
            _actionExceptionHandler = actionExceptionHandler;
            _getActionTransactionHelper = getActionTransactionHelper;
            _actionTransactionHelper = null;
        }
    
        public override void OnActionExecuting(ActionExecutingContext actionExectingContext)
        {
            _actionTransactionHelper = _getActionTransactionHelper();
            _actionLogHelper.LogEntry(actionExectingContext.ActionDescriptor);
            _actionTransactionHelper.BeginTransaction();
        }
    
        /* your code */
    }
    
    公共类LoggingHibernateSessionAttribute:ActionFilterAttribute
    {
    /*你的代码*/
    私有只读函数_getActionTransactionHelper;
    私有IActionTransactionHelper\u actionTransactionHelper;
    公共日志JubernateSessionAttribute()
    :此(WebContainerManager.Get(),
    WebContainerManager.Get(),
    ()=>WebContainerManager.Get())
    {
    }
    公共日志HibernateSessionAttribute(
    IActionLogHelper操作LogHelper,
    IActionExceptionHandler actionExceptionHandler,
    Func getActionTransactionHelper)
    {
    _actionLogHelper=actionLogHelper;
    _actionExceptionHandler=actionExceptionHandler;
    _getActionTransactionHelper=getActionTransactionHelper;
    _actionTransactionHelper=null;
    }
    公共覆盖无效OnActionExecuting(ActionExecutingContext ActionExecutingContext)
    {
    _actionTransactionHelper=\u getActionTransactionHelper();
    _actionLogHelper.LogEntry(ActionExecutingContext.ActionDescriptor);
    _actionTransactionHelper.BeginTransaction();
    }
    
    public class LoggingNHibernateSessionAttribute : ActionFilterAttribute
    {
        /* your code */
        private readonly Func<IActionTransactionHelper> _getActionTransactionHelper;
        private IActionTransactionHelper _actionTransactionHelper;
    
        public LoggingNHibernateSessionAttribute()
            : this(WebContainerManager.Get<IActionLogHelper>(),
            WebContainerManager.Get<IActionExceptionHandler>(),
            () => WebContainerManager.Get<IActionTransactionHelper>())
        {
        }
    
        public LoggingNHibernateSessionAttribute(
            IActionLogHelper actionLogHelper,
            IActionExceptionHandler actionExceptionHandler,
            Func<IActionTransactionHelper> getActionTransactionHelper)
        {
            _actionLogHelper = actionLogHelper;
            _actionExceptionHandler = actionExceptionHandler;
            _getActionTransactionHelper = getActionTransactionHelper;
            _actionTransactionHelper = null;
        }
    
        public override void OnActionExecuting(ActionExecutingContext actionExectingContext)
        {
            _actionTransactionHelper = _getActionTransactionHelper();
            _actionLogHelper.LogEntry(actionExectingContext.ActionDescriptor);
            _actionTransactionHelper.BeginTransaction();
        }
    
        /* your code */
    }