带TransactionScope的NHibernate

带TransactionScope的NHibernate,nhibernate,transactionscope,Nhibernate,Transactionscope,有人能给我一个使用TransactionScope与NHibernate的快速概述吗?我是否需要对会话/IEnlistmentNotification/等执行任何特殊操作才能使其正常工作?有什么陷阱我应该担心吗?例如,我是否可以替换所有hibernate事务: var transaction = session.BeginTransaction(); try { // code transaction.Commit(); } catch (Exception) { tra

有人能给我一个使用TransactionScope与NHibernate的快速概述吗?我是否需要对会话/IEnlistmentNotification/等执行任何特殊操作才能使其正常工作?有什么陷阱我应该担心吗?例如,我是否可以替换所有hibernate事务:

var transaction = session.BeginTransaction();
try
{
    // code
    transaction.Commit();
}
catch (Exception)
{
    transaction.Rollback();
}
用这个

using (var scope = new TransactionScope())
{
    // code
    scope.Complete();
}

我已经使用不同的供应商对此进行了测试,而且效果很好。如果没有“scope.Complete()”,则事务将回滚。如果存在多个持久资源,则可能需要让MSDTC运行所涉及的计算机。在这种情况下,MSDTC将自动检测环境ADO.NET事务并管理整个事务。

如果您使用的是支持使用轻型事务管理器(如SQL Server 2005/2008)的连接提供程序,则上述操作正常

如果您使用的是SQL Server 7/2000,那么即使只访问一个数据库/资源,您的所有事务都将成为分布式事务。在大多数情况下,这可能不是您想要的,而且在性能方面会非常昂贵


因此,请检查您的连接提供程序和数据库服务器组合是否适合与TransactionScope一起使用。

此外,如果您正在使用TransactionScope,请升级到NHibernate 2.1。只有在2.1版本中,NH才真正与TransactionScope实现了良好的集成。

根据Fabio Maulo在以下相关评论中的说法:

您可以使用TransactionScope,也应该继续使用NH的事务。 您阅读过TransactionScope的使用意味着避免使用NH的交易吗


我认为明确使用NHibernate的事务是不必要的,但这是最佳实践

我使用NHibernate 2.1已经有一段时间了,在一些生产问题和尝试了许多变化后,我们按照以下方法达成了一致:

因为我们使用的是MSMQ和WCF,所以我们不得不使用环境事务

我们发现未使用session.BeginTransaction()导致连接泄漏。
我们还发现,提交事务后重新使用会话会导致竞争条件(nHibernate不是线程安全的,DTSC提交/回滚发生在后台线程上)

我相信,只要您尊重一些约束条件,您就可以用它取代NHibernate交易,正如一些人已经说过的:

  • 使用合理最新的NHibernate版本()
  • 底层ADO.NET数据提供程序必须支持TransactionScope(对于SQL Server,ok;对于ODP.NET,Oracle>=10)
  • 在TransactionScope中创建您的NH会话,以确保它被登记
  • 手动处理NHibernate。另见和
  • 准备分布式事务。 如果在一个作用域中创建多个会话,则最初的本地事务可能会升级为分布式事务。即使使用ODAC 11.2.0.3.20在Oracle 11.2 DB上使用相同的连接字符串,我也看到了这种情况。在SQL Server 2008 R2上,它没有升级。(顺便说一句,您可以通过查看Transaction.Current.TransactionInformation.DistributedIdentifier(对于本地事务为空)来了解这一点。)虽然分布式事务有一些优势,但它们的成本更高,而且设置它们会带来额外的痛苦。(请参见如何为Oracle执行此操作)。为了确保升级不会在Oracle中发生,请在连接字符串中设置“=local”。如果某些代码试图这样做,这将创建一个异常
我希望就这些;-)


附:我添加了Oracle的详细信息,因为这些信息可能会让我和其他人受益。

@Rohit-你能提供更多的详细信息吗?错;默认情况下,TransactionScope使用监视升级的轻量级事务管理器。来自MSDN:只要最多涉及一个持久资源管理器,就让底层资源(如Microsoft SQL Server 2005)管理事务没有什么错。在这种情况下,LTM根本不需要实际管理事务,它的角色应该简化为监视事务以满足升级的需要。此外,SqlConnection-s(如果是您的DB)在幕后汇集,2)您可以从单个线程打开多个线程,而无需升级事务,只要它们不共享事务。推广交易意味着开始使用MSDTC。我仍然在寻找关于这个问题的权威答案。在NH 3.0中,显式使用似乎没有必要——也许是为了让自动刷新正常工作。这也会导致SQL Compact出现问题(试图创建嵌套事务,这对我来说似乎是一个bug):我在这里更新了Andrew的链接,讨论发生的地方:不要认为这种情况仍然存在(截至2019年4月4日)。当前文档读取:
可以使用TransactionScope,而不是使用NHibernate ITransaction。请不要同时使用两者。
Reference:这似乎不起作用,内部事务是在父作用域完成之前提交的,这意味着父作用域上发生了id故障。事务没有回滚。您确定吗?你测试过了吗?从内存来看,内部事务与父作用域不是“独立”的。直到
scope.Complete()
,事务才真正提交。嘿,谢谢你的回复,我知道这篇文章很老了。我希望这会像你说的那样,但事实似乎并非如此。我们已经对它进行了测试,看看我在这里做的测试:,(很抱歉没有时间简化sessionFactory的内容,所以有点冗长)乍一看,为什么第165行断言0,而第162行保存了1。为什么第162行还在那里?我不再写那个代码了,我的记忆也消失了。你看起来很面熟。我记得的是因为事务在后台线程上提交,当它提交时,主线程已经重新打开了会话。然后是背景线程cl
        using (var scope = new TransactionScope(TransactionScopeOption.Required))
        {
            using (var session = sessionFactory.OpenSession())
            using (var transaction = session.BeginTransaction())
            {
                // do what you need to do with the session
                transaction.Commit();
            }
            scope.Complete();
        }