Сбой области транзакции с BeginTransaction в Oracle: соединение уже является частью локальной или распределенной транзакции

Такое странное поведение при использовании OracleConnection с 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 (). Если бы эти библиотеки использовали TransactionScope, моя внешняя транзакция не была бы проблемой. Распределенная транзакция будет обработана без каких-либо проблем. Но я не могу изменить код внутри dll.

И почему db.BeginTransaction () работает для SqlServer, но не для Oracle?


person adt    schedule 29.07.2011    source источник


Ответы (4)


Я задал тот же вопрос в связи с NHibernate. Другие ответы указывают на то, что не следует смешивать TransactionScope и BeginTransaction. К сожалению, источники, подтверждающие это утверждение, не добавлены. Вот мое исследование: Как указано в MSDN (поиск по запросу "mix" ) и в этом обсуждении, не следует смешивать обе концепции, даже для SQL-Server. Мне все еще не ясно, почему это работает для SQL-Server как для локальных, так и для распределенных транзакций.

Некоторые думают, что это глупый вопрос, но он имеет смысл, если рассматривать его в контексте NHibernate (см. здесь, здесь и здесь).

person Piper    schedule 28.02.2013
comment
Спасибо, Пайпер .. Я тоже столкнулся с подобной проблемой. Ссылки, которыми вы поделились, действительно полезны. - person Jaqen H'ghar; 15.12.2016

TransactionScope и DbConnection.BeginTransaction - это два эксклюзивных способа управления транзакциями. Вы используете любой из них.

В тот момент, когда вы вызываете OracleConnection.Open, соединение оракула зачисляется. в транзакции внешней системы. Все, что вам затем нужно сделать, это вызвать TransactionScope.Complete (), если вы хотите зафиксировать транзакцию или не вызывать ее, и в этом случае системная транзакция откатывается. В случае, если вы не хотите сразу подключаться к «Открыть», вы можете установить для атрибута строки подключения «enlist» значение «dynamic», а затем явно подключиться с помощью вызова 'OracleConnection.EnlistTransaction '

person alwayslearning    schedule 29.07.2011
comment
Я знаю, что они разные, я на самом деле немного отредактировал, но мой вопрос все еще остается. Почему это работает для Sql Server, но не для Oracle? - person adt; 29.07.2011

Вам следует дополнительно прочитать TransactionScope

Прежде всего перечисление TransactionScopeOption

Обязательно:

Транзакция требуется в соответствии с областью действия. Он использует внешнюю транзакцию, если она уже существует. В противном случае перед входом в область действия создается новая транзакция. Это значение по умолчанию.

Таким образом, транзакция, если она недоступна, создается и автоматически связывается.

Внешняя транзакция - это транзакция, в которой выполняется ваш код. Вы можете получить ссылку на внешнюю транзакцию, вызвав статическое свойство Current класса Transaction.

person V4Vendetta    schedule 29.07.2011

Вы не должны использовать внутренний объект транзакции, TransactionScope создание уже делает это, а метод Complete выполняет фиксацию, внутренние вызовы методов BeginTransaction и Commit не требуются.

Как это будет работать, если вы пойдете по этому пути?

person Davide Piras    schedule 29.07.2011
comment
это отлично работает (я немного отредактировал вопрос). Но почему использование BeginTransaction и Commit работает для Sqlserver, а не для Oracle. - person adt; 29.07.2011