我如何在NHibernate中进行嵌套事务?

Gav*_*vin 18 sql-server nhibernate session transactions nested

我可以在NHibernate中进行嵌套事务,我该如何实现它们?我正在使用SQL Server 2008,所以支持肯定在DBMS中.

我发现如果我尝试这样的事情:

using (var outerTX = UnitOfWork.Current.BeginTransaction())
{
    using (var nestedTX = UnitOfWork.Current.BeginTransaction())
    {
        ... do stuff
        nestedTX.Commit();
    }

    outerTX.Commit();
}
Run Code Online (Sandbox Code Playgroud)

然后到outerTX.Commit()事务处理变为非活动状态时,会在会话AdoTransaction上产生ObjectDisposedException.

因此我们应该创建嵌套的NHibernate会话吗?或者是否有其他类我们应该使用它来包装事务(我听说过TransactionScope,但我不确定那是什么)?

我现在正在使用Ayende的UnitOfWork实现(感谢Sneal).

原谅这个问题的任何天真,我还是NHibernate的新手.

谢谢!

编辑:我发现你可以使用TransactionScope,例如:

using (var transactionScope = new TransactionScope())
{
    using (var tx = UnitOfWork.Current.BeginTransaction())
    {
        ... do stuff
        tx.Commit();
    }

    using (var tx = UnitOfWork.Current.BeginTransaction())
    {
        ... do stuff
        tx.Commit();
    }

    transactionScope.Commit();
}
Run Code Online (Sandbox Code Playgroud)

但是我对此并不是很兴奋,因为它锁定了我们使用SQL Server,而且我发现如果数据库是远程的,那么你必须担心启用MSDTC ...还有一个组件要去错误.嵌套事务在SQL中是如此有用和容易,我认为NHibernate可以通过某种方式模拟相同的...

Sat*_*aga 14

NHibernate会话不支持嵌套事务.

以下测试在2.1.2版中始终如此:

var session = sessionFactory.Open();
var tx1 = session.BeginTransaction();
var tx2  = session.BeginTransaction();
Assert.AreEqual(tx1, tx2);
Run Code Online (Sandbox Code Playgroud)

您需要将其包装在一个TransactionScope以支持嵌套事务.

必须启用MSDTC,否则您将收到错误:

{"Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool."}


Sne*_*eal 1

该实现不支持嵌套,如果您想要嵌套,请使用Ayende 的 UnitOfWork 实现。您使用的实现(至少对于 Web 应用程序)的另一个问题是它在静态变量中保存 ISession 实例。

由于这些原因,我昨天刚刚重写了我们的 UnitOfWork,它最初是基于 Gabriel 的。

我们不使用UnitOfWork.Current.BeginTransaction(),我们使用UnitofWork.TransactionalFlush(),它在最后创建一个单独的事务来立即刷新所有更改。

using (var uow = UnitOfWork.Start())
{
     var entity = repository.Get(1);
     entity.Name = "Sneal";
     uow.TransactionalFlush();
}
Run Code Online (Sandbox Code Playgroud)