1

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

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 和每个请求的会话有缺陷?有什么建议么?

4

1 回答 1

8

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

通常对于每个 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();
    }
}

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

于 2012-11-03T05:24:57.343 回答