我试图在分布式事务下更新 DB2 数据库(通过 NHibernate),但它总是失败。
这是我写的代码:
public bool ExecuteUsingDTC(List<Func<bool>> tasks)
{
var result = false;
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
using (var session = sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
//carry out db modification tasks
tasks.ForEach(task => { result = result && task.Invoke(); })
transaction.Commit();
}
scope.Complete();
}
return result;
}
我不断收到异常:
NHibernate.TransactionException was unhandled by user code
Message=Begin failed with SQL exception
Source=NHibernate
StackTrace:
at NHibernate.Transaction.AdoTransaction.Begin(IsolationLevel isolationLevel)
at NHibernate.Transaction.AdoTransaction.Begin()
at NHibernate.AdoNet.ConnectionManager.BeginTransaction()
at NHibernate.Impl.SessionImpl.BeginTransaction()
at DTCProofOfConcept_Repository.ExecuteUsingDTC(List`1 tasks) in C:\Project\Infrastructure\GlobalRepositories\DTCProofOfConcept_Repository.vb:line 20
at
InnerException: IBM.Data.DB2.DB2Exception
ErrorCode=-2147467259
Message=ERROR [HY011] [IBM] CLI0126E Operation invalid at this time. SQLSTATE=HY011
Source=IBM.Data.DB2
StackTrace:
at IBM.Data.DB2.DB2Connection.HandleError(IntPtr hHandle, SQL_HANDLE hType, RETCODE retcode)
at IBM.Data.DB2.DB2Transaction.set_AutoCommit(Boolean value)
at IBM.Data.DB2.DB2Transaction.BeginTransaction()
at IBM.Data.DB2.DB2Connection.BeginTransactionObject(IsolationLevel isolevel)
at IBM.Data.DB2.DB2Connection.BeginTransaction(IsolationLevel isolevel)
at IBM.Data.DB2.DB2Connection.BeginTransaction()
at IBM.Data.DB2.DB2Connection.System.Data.IDbConnection.BeginTransaction()
at NHibernate.Transaction.AdoTransaction.Begin(IsolationLevel isolationLevel)
InnerException:
最佳答案
像这样使用 TransactionScope
using(var scope = new TransactionScope(...))
{
transaction.Complete();
}
开始并为您提交交易。如果抛出异常,则事务将在未调用 Complete 的情况下被释放的范围中止。
我怀疑您的问题是您对 BeginTransaction/Commit 进行了额外的显式调用。删除那些并假设 NHibernate 与 TransactionScope 配合得很好,一切都应该没问题。
使用 TransactionScope 可能涉及使用分布式事务协调器 (DTC)。如果是这样,您需要打开管理工具|组件服务。导航到分布式事务处理协调器|本地 DTC。右键单击,属性,安全选项卡。启用安全性,并作为开始启用一切。如果这可行,请阅读 DTC 安全性并将其减少到最低限度。
或者按照 DanVallejo 的建议删除 TransactionScope 并只使用您的显式事务。
关于c# - 如何使用交易范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10390680/