事务作用域在Oracle中使用BeginTransaction失败:连接已经是本地或分布式事务的一部分

本文关键字:事务 一部分 分布式 Oracle 作用域 失败 BeginTransaction 连接 | 更新日期: 2023-09-27 18:03:49

在使用oraclecontion与TransactionScope时出现这种奇怪的行为。如果我尝试在事务范围内使用Connection . begintransaction(),我会得到简单优雅的InvalidOperationException:连接已经是本地或分布式事务的一部分。

下面是一些代码:
var trxOptions = new TransactionOptions();
 trxOptions.IsolationLevel = IsolationLevel.ReadCommitted;
 using (var transaction = new TransactionScope(TransactionScopeOption.Required,trxOptions))
            {
                var c = ConfigurationManager.ConnectionStrings["oracle_test"].ConnectionString;
                using (var oracle = new OracleConnection(c))
                {
                    oracle.Open();
                    using (var tr = oracle.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
                    {
                        var cmd = oracle.CreateCommand();
                        cmd.CommandText = "INSERT INTO simple_user VALUES('a')";
                        cmd.ExecuteNonQuery();
                        tr.Commit();
                    }
                }

        // now go to sql server and insert data
       transaction.Complete();

}

如果我不使用BeginTransaction一切工作。有什么可行的办法吗?

PS:我在Sql Server上没有这样的问题。

编辑

谢谢你的回答,我想我应该添加一些编辑使我的问题更清楚。首先,我上面提供的代码是对问题的演示。假设我有两个dll的MyProject.Oracle.dll和MyProject2.MsSql.dll,我想在这些dll中使用方法,他们使用db.BeginTransaction()。如果这些dll使用了TransactionScope,我的外部事务就不会有问题了。分布式事务处理没有任何问题。但是我不能更改dll中的代码。

为什么db.BeginTransaction()适用于SqlServer而不适用于Oracle?

事务作用域在Oracle中使用BeginTransaction失败:连接已经是本地或分布式事务的一部分

我在使用NHibernate时遇到了同样的问题。其他答案表明不要混合TransactionScope和BeginTransaction。不幸的是,没有任何来源支持这一说法。以下是我的研究:正如MSDN(搜索"mix")和本讨论中所述,不应该混合这两个概念,即使对于SQL-Server也是如此。为什么它似乎对SQL-Server工作,对于本地和分布式事务,我仍然不清楚。

有些人似乎认为这是一个愚蠢的问题,但它在NHibernate的上下文中是有意义的(见这里,这里和这里)。

TransactionScope和DbConnection。BeginTransaction是两种独立的事务管理方式。你可以用其中任意一个。

调用oracleconconnection的那一刻。打开时,oracle连接在环境系统事务中登记。然后你所需要做的就是调用TransactionScope.Complete(),如果你想提交事务或者不调用它,在这种情况下系统事务被回滚。如果你不想在'Open'上立即招募,你可以将'enlist'连接字符串属性设置为'dynamic',然后通过调用' oraclecconnection显式招募。EnlistTransaction '

它适用于SQL/Server而不是Oracle的原因是SQL/Server支持嵌套事务而Oracle不支持

你应该多读一些关于TransactionScope

首先是TransactionScopeOption

的枚举需要

:

事务是范围所需要的。它使用环境事务如果已经存在的话。否则,它会创建一个新的事务进入作用域。这是默认值

如果事务不可用,则创建并自动关联。

环境事务是执行代码的事务。您可以通过调用transaction类的静态Current属性来获取对环境事务的引用。

你不应该使用内部Transaction对象,TransactionScope创建已经做了,Complete方法做了提交,不需要内部BeginTransactionCommit方法调用。

如果你这样做,它是如何工作的?