Проблемы с TransactionScope и Oracle

мы написали клиент C # 3.5, говорящий с базой данных Oracle (11g) с использованием ODP.NET.

Это приложение имеет пакетный процесс, в котором выполняется долго выполняемая задача, выполняющая различные вызовы базы данных в TransactionScope.

В нашей среде разработки все идет хорошо, но в среде UAT одного из наших клиентов (у которого много данных) возникают две чередующиеся (иногда одна, иногда другая ...) ошибки:

Невозможно подключиться к распределенной транзакцииТранзакция прервана. (внутреннее исключение: тайм-аут транзакции)

В настоящее время мы используем тайм-ауткогда-нибудь для транзакции (для целей тестирования).

Запуск указанного процесса в среде UAT приводит к остановке через прибл. 10 минут с одним из вышеперечисленных исключений, поэтому значение не должно превышать тайм-аут.

Вот фрагмент трассировки стека для второй ошибки:

at System.Transactions.TransactionStatePromotedAborted.CreateAbortingClone(InternalTransaction tx)
   at System.Transactions.DependentTransaction..ctor(IsolationLevel isoLevel, InternalTransaction internalTransaction, Boolean blocking)
   at System.Transactions.Transaction.DependentClone(DependentCloneOption cloneOption)
   at System.Transactions.TransactionScope.SetCurrent(Transaction newCurrent)
   at System.Transactions.TransactionScope.PushScope()
   at System.Transactions.TransactionScope..ctor(TransactionScopeOption scopeOption)
   at System.Transactions.TransactionScope..ctor()
   at Application.Domain.DataAccess.Oracle.EntityDaoBase`2.SaveItem(TEntity item, EntityReference`1 user)

Процесс пытается сохранить элемент в БД в области транзакции, но трассировка стека показывает, что для конструктора применен класс TransactionScope, то есть создается новый TransactionScope.

Я прав до сих пор?

Поскольку я мало знаю о внутренней работе TransactionScope, но, похоже, когда вы вызываете метод в области действия, он создаст новую транзакцию (предположительно наследуя от внешней транзакции).

Может ли быть так, что, если я прав, эта новая транзакция не наследует правильный тайм-аут (но по умолчанию), так что вложенная транзакция вызовет это исключение тайм-аута?

Если нет, какие-либо мысли о том, что это может быть? Напомним, что вложенные транзакции не определены в методах, вызываемых из внешней транзакции.

Любая помощь будет принята с благодарностью!

Изменить 1:

Упрощенный фрагмент кода функции:

public void SomeLengthyBatchProcess()
{
   using (var transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0)))
   {
       foreach (var item in Items)
       {
          SaveItemToDB(item);
       }

       transaction.Complete();
   }
}

public void SaveItemToDB(object item)
{
   using (var transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0)))
   {
       // Performing data persistency here

       transaction.Complete();
   }
}

Изменить 2:

Ладно, так получается, чтоявляется вложенная транзакция происходит в методе «SaveItemToDB». После некоторого изучения кода, созданного коллегой, я увидел, что у него определен собственный TransactionScope, но без параметров и времени ожидания.

После изменения этого метода, чтобы он имел те же параметры, что и время ожидания, я снова запустил код на сервере клиента, но все равно не повезло (снова транзакция прервала ошибку с истечением времени ожидания).

Итак, мои вопросы сейчас таковы:

Необходимо ли определять значения времени ожидания для вложенных транзакций или они наследуют это от внешней транзакции?Как это возможно, что исключение тайм-аута может возникать, когда параметр тайм-аута (предположительно, помимо внутренних операций, о которых я не знаю) одинаков для всех областей транзакции и имеет значение тайм-аута, определенное в 1 день, когда исключение возникает после ок. 10 минут?Можно ли предотвратить создание Oracle распределенной транзакции для транзакций, в которых строка подключения одинакова?Может ли быть так, что дополнительные издержки распределенной транзакции вызывают исключения, такие как транзакция, прерванная?

Я обновил фрагмент кода, чтобы он лучше отражал ситуацию.

(кстати: вторая, вложенная транзакция необходима, поскольку DAL также отдельно сохраняет некоторые дочерние элементы, если они есть, и, конечно, весь элемент должен быть откатан, если что-то пойдет не так при сохранении дочерних элементов)

Надеемся, что с этим дополнением будет легче пролить свет на этот вопрос!

Ответы на вопрос(6)

Ваш ответ на вопрос