English 中文(简体)
使用TransactionScope的NHibernate
原标题:
  • 时间:2009-03-14 17:33:07
  •  标签:

有人能给我简要概述如何在 NHibernate 中使用 TransactionScope 吗? 我需要在会话/ IEnlistmentNotification 等方面做任何特殊的事情才能使其正常工作吗? 有什么我应该担心的陷阱吗?例如,我可以替换我所有的 hibernate 事务吗?

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

这个?

using (var scope = new TransactionScope())
{
    // code
    scope.Complete();
}
问题回答

我已经使用nHibernate 2.1有一段时间了,在经历了一些生产问题并尝试了很多方法后,我们根据避免NHibernate和TransactionScope泄漏连接的建议,选择了以下方法:

        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();
        }

因为我们正在使用MSMQ和WCF,所以我们必须使用环境事务。

We found that not using session.BeginTransaction() caused a connection leak. We also found that re-using a session after committing a transaction caused a race condition (nHibernate is not thread safe and DTSC Commits/Rollbacks occur on a background thread).

我已经使用不同的供应商进行测试,它完全有效。如果你没有“scope.Complete()”,那么事务将会回滚。如果存在多个持久化资源,则可能需要在涉及的计算机上运行MSDTC。在这种情况下,MSDTC将自动检测环境中的ADO.NET事务并管理整个过程。

以上工作只有在使用支持轻量级事务管理器的连接提供程序时才能正常进行,例如 SQL Server 2005/2008。

如果您正在使用SQL Server 7/2000,则即使您只访问一个数据库/资源,所有交易也将变为分布式交易。 这在大多数情况下可能不是您想要的,并且会影响性能。

请检查您的连接提供者和数据库服务器组合是否适合使用TransactionScope。

我相信只要你遵守一些限制,就可以使用这个替代NHibernate事务,就像一些人已经说过的那样:

  • Use a reasonably recent NHibernate version (>=3.1).
  • The underlying ADO.NET data provider must support TransactionScope (ok for SQL-Server, Oracle >= 10 with ODP.NET).
  • Create your NH session within the TransactionScope to ensure it gets enlisted.
  • Handle NHibernate flushing manually. See also here and here.
  • Prepare for distributed transactions. If you create multiple sessions in one scope, the initially local transaction might get promoted to a distributed transaction. I saw this happen even with same connection strings on an Oracle 11.2 DB using ODAC 11.2.0.3.20. On SQL-Server 2008 R2 it did not promote. (BTW, one can see this by watching Transaction.Current.TransactionInformation.DistributedIdentifier which is null for local transactions.) While distributed transactions have some advantages, they are more expensive and it is some extra pain setting them up. (See here how to do this for Oracle). To be sure promotion never happens in Oracle, set "Promotable Transaction=local" in your connection string. This creates an exception if some code tries to do so.

我希望那就是全部的了 ;-)

附注:我添加了Oracle的细节,因为它们是我的关注点,其他人可能会受益。

此外,如果您使用TransactionScope,请升级到NHibernate 2.1。仅有2.1,NHibernate才真正获得了与TransactionScope的良好集成。

根据Fabio Maulo在与NH-2107相关的评论中所述:

You can use TransactionScope and you should continue using NH s transaction too. Where you have read that the Usage of TransactionScope mean the avoid of usage of NH s transaction ?

我本以为NHibernate的事务的明确使用是不必要的,但显然这是最佳实践。





相关问题
热门标签