当前位置:  开发笔记 > 数据库 > 正文

NHibernate与TransactionScope

如何解决《NHibernate与TransactionScope》经验,为你挑选了4个好方法。

任何人都可以快速概述一下使用TransactionScope和NHibernate吗?我是否需要对session/IEnlistmentNotification/etc执行任何特殊操作.让这个工作?有什么陷阱我应该担心吗?例如,我可以替换所有的hibernate事务:

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

有了这个?:

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

Iain.. 18

我已经使用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,因此我们不得不使用环境事务.

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



1> Iain..:

我已经使用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,因此我们不得不使用环境事务.

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



2> Adam Fyles..:

我使用不同的供应商测试了它,它只是有效.如果您没有"scope.Complete()",则事务将回滚.如果有多个持久资源,您可能需要让MSDTC运行所涉及的机器.在这种情况下,MSDTC将自动检测环境ADO.NET事务并管理整个事务.


错误; 默认情况下,TransactionScope使用轻量级事务管理器监视升级.来自MSDN:只要涉及最多一个持久资源管理器,让底层资源(例如Microsoft SQL Server 2005)管理事务没有任何问题.在这种情况下,LTM根本不需要实际管理交易 - 应该减少其角色以监控交易以满足促销需求.

3> 小智..:

如果您正在使用支持使用轻量级事务管理器的连接提供程序,例如SQL Server 2005/2008,则上述工作正常.

如果您使用的是SQL Server 7/2000,那么即使您只打了一个数据库/资源​​,您的所有事务也将成为分布式事务.在大多数情况下,这可能不是您想要的,并且性能代价高昂.

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



4> Piper..:

我相信只要遵守一些约束,就可以用NHibernate事务替换它:

使用合理的最新NHibernate版本(> = 3.1)。

底层的ADO.NET数据提供程序必须支持TransactionScope(对于SQL Server,对于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来看到这一点,对于本地事务为null。)尽管分布式事务有一些优势,但它们更昂贵,并且设置起来有些麻烦。(请参阅此处如何针对Oracle执行此操作)。为确保升级永远不会在Oracle中发生,请在连接字符串中设置“ Promotable Transaction = local”。如果某些代码尝试这样做,则会创建一个异常。

我希望就这些;-)

PS:我添加了Oracle详细信息,因为它们会使我的关注点和其他方面受益。

推荐阅读
围脖上的博博_771
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有