Объем транзакции завершается неудачно с BeginTransaction в Oracle: соединение уже является частью локальной или распределенной транзакции - PullRequest
6 голосов
/ 29 июля 2011

Такое странное поведение при использовании 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.

Edit

Спасибо за ответы, я полагаюЯ должен добавить некоторые изменения, чтобы прояснить мой вопрос.

Прежде всего, приведенный выше код является демонстрацией проблемы.Допустим, у меня есть две библиотеки DLL MyProject.Oracle.dll и MyProject2.MsSql.dll, и я хочу использовать методы внутри этих библиотек DLL, и они используют db.BeginTransaction ().Если бы эти dll использовали TransactionScope, моя внешняя транзакция не была бы проблемой.Распределенная транзакция будет обработана без каких-либо проблем.Но я не могу изменить код внутри dll.

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

Ответы [ 4 ]

3 голосов
/ 28 февраля 2013

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

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

1 голос
/ 29 июля 2011

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

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

0 голосов
/ 29 июля 2011

Вы должны сделать еще несколько чтений по TransactionScope

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

Требуется:

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

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

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

0 голосов
/ 29 июля 2011

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

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

...