带有TransactionScope错误的Nhibernate - DTC事务预处理阶段失败 - 升级到Nhibernate 3.0

时间:2011-02-08 06:21:14

标签: nhibernate transactionscope

在事务Scope.Eg中使用Nhibernate和ADO.Net操作时,我收到以下异常。 Nhibernate 2.1很好,但现在升级到3.0,这会引发错误。

using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
        GetmemberId(); --> NHibernate Call
        Update(); ADO Call OracleDB
}

由于这充当了环境事务,Nhibernate试图在外部事务完成之前很快处理事务。如果我错了,请修正我,是否有任何解决方案因为帮助我,但是当我在TransactionScope外部移动Nhibernate调用时一切正常。我给出的示例是示例一,mines涉及更复杂的一个,因为我在TransactionScope中保留了两个调用,并且Iam得到的错误如下,

  

错误13 NHibernate.Impl.AbstractSessionImpl - DTC事务预处理   阶段失败System.ObjectDisposedException:无法访问已处置的   宾语。对象名称:'交易'。在   System.Transactions.Transaction.DependentClone(DependentCloneOption   cloneOption)   System.Transactions.TransactionScope.SetCurrent(交易   System.Transactions.TransactionScope.PushScope()的newCurrent   在System.Transactions.TransactionScope.Initialize(Transaction   transactionToUse,TimeSpan scopeTimeout,Boolean interopModeSpecified)   在System.Transactions.TransactionScope..ctor(交易   transactionToUse)at   NHibernate.Transaction.AdoNetWithDistributedTransactionFactory.DistributedTransactionContext.System.Transactions.IEnlistmentNotification.Prepare(PreparingEnlistment   准备入境)2011-02-08 13:41:46,033错误13   NHibernate.Impl.AbstractSessionImpl - DTC事务预处理阶段   System.ObjectDisposedException失败:无法访问已释放的   宾语。对象名称:'交易'。在   System.Transactions.Transaction.DependentClone(DependentCloneOption   cloneOption)   System.Transactions.TransactionScope.SetCurrent(交易   System.Transactions.TransactionScope.PushScope()的newCurrent   在System.Transactions.TransactionScope.Initialize(Transaction   transactionToUse,TimeSpan scopeTimeout,Boolean interopModeSpecified)   在System.Transactions.TransactionScope..ctor(交易   transactionToUse)at   NHibernate.Transaction.AdoNetWithDistributedTransactionFactory.DistributedTransactionContext.System.Transactions.IEnlistmentNotification.Prepare(PreparingEnlistment   preparingEnlistment)

2 个答案:

答案 0 :(得分:6)

尝试

Configuration.SetProperty(Environment.TransactionStrategy,"NHibernate.Transaction.AdoNetTransactionFactory")

或者在nhibernate配置

<property name="transaction.factory_class">
NHibernate.Transaction.AdoNetTransactionFactory
</property>

它对我有用=)

答案 1 :(得分:1)

我们遇到了同样的错误,这是由我们使用NHibernate在Web Api中使用会话和事务的方式引起的。

我们应该一直在使用session-per-request。 (这可以是Web请求或执行NServiceBus处理程序。)当请求启动时,您应该打开一个会话并启动一个事务。

我们没有这样做。在我们的存储库中,我们为每个数据库请求创建了一个新的会话和事务。这意味着我们有很多,而不是为请求提供单个会话/事务。

我们的错误的根本原因是我们在一个会话中加载一个实体(域模型对象),修改它,并使用不同的会话保存它。当NHibernate执行更新调用时,加载会话/事务已经被提交,刷新和关闭。

解决方案是将我们的会话/事务创建从存储库中拉出到Controller层(可以使用HttpModule进行REST调用和/或使用依赖注入进行面向方面编程)。然后,这一个会话/事务将在REST调用或NServiceBus处理程序执行的生命周期中存在,并在该调用期间用于所有数据库访问。当该呼叫结束时,它将在适当时提交或回滚。

上面给出的答案设置配置属性只是关闭DTC并恢复到旧的NHibernate事务处理方式。如果您不必将Web Api扩展到多个实例,这可能会为您解决问题,但如果您这样做,这将导致您出现问题。