【问题标题】:Unit of Work in NHibernate and Session per RequestNHibernate 中的工作单元和每个请求的会话
【发布时间】:2012-10-23 05:51:30
【问题描述】:

我认为我的架构中的工作单元设置可能有误。这是我目前拥有的(缩进以显示顺序):

HttpRequest.Begin()
  UnitOfWork.Begin()
    Session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);

在这里,我调用各种服务来使用 NHibernate 执行 crud。当我想对数据库进行更改(更新/保存)时,我调用此代码:

        using (var transaction = unitOfWork.Session.BeginTransaction())
        {
            try
            {
                // These are just generics
                ret = (Key)unitOfWork.Session.Save(entity);
                transaction.Commit();
                rb.unitOfWork.Session.Clear();
            }
            catch
            {
                transaction.Rollback();
                rb.unitOfWork.Session.Clear();
                rb.unitOfWork.DiscardSession();
                throw;
            }
        }

当 HttpRequest 结束时,我执行以下步骤:

      UnitOfWork.Commit()
    Transaction.Commit() // This is my sessions transaction from the begin above

我遇到了能够回滚大批量进程的问题。因为我在我的 CRUD 层中提交我的事务,如上所示,我的事务不再处于活动状态,当我尝试在我的 UnitOfWork 中回滚时,它什么也不做,因为事务已经被提交。我在我的 CRUD 层中提交我的代码的原因是我可以尽可能快地保存我的数据,而不会锁定数据库太久。

对于上述情况,最好的行动方案是什么?我是否只是进行不提交批处理作业的特殊 CRUD 操作,而只是在我的工作结束时处理提交,还是我的逻辑与我的 UnitOfWork 和每个请求的会话有缺陷?有什么建议吗?

【问题讨论】:

    标签: c# nhibernate unit-of-work session-per-request


    【解决方案1】:

    您已经发现了每次请求会话模式如此流行的原因以及可能源于对工作单元进行微观管理的问题。

    通常对于每个 Web 请求,需要在该请求中完成的所有事情都可以被视为一个工作单元,因此您应该只在该单个 Web 期间打开一个工作单元和一个 NHibernate 会话。请求。

    另外,我认为您可能会对 NHibernate 的工作原理感到有些困惑,因为您的问题中有这句话:“我在 CRUD 层中提交代码的原因是,我可以尽快保存我的数据,而无需锁定数据库的时间过长。”

    NHibernate 不会在您的数据库中造成任何锁定。每次调用 ISession.Save(entity) 时,只要不调用 ISession.Flush() 或 ITransaction.Commit(),就不会向数据库写入任何内容,而是将其添加到要插入的项目队列中或在 Web 请求结束时提交当前事务时在数据库中更新。

    所以你的每个请求的会话应该这样设置:

    void Application_BeginRequest()
    {
        // Start your unit of work, open a session and begin a transaction
    }
    
    // Do all of your work ( Read, insert, update, delete )
    
    void Application_EndRequest()
    {
        try
        {
            // UnitOfWork.Current.Transaction.Commit();
        }
        catch( Exception e )
        {
            // UnitOfWork.Current.Transaction.Rollback();
        }
    }
    

    当然有很多方法可以做同样的事情,但这是每个请求会话模式的基础——整个网络请求只有一个会话。

    【讨论】:

    • 迄今为止我找到的最简单的完整解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2012-06-30
    • 2017-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多