2009-10-26 2 views
4

У меня есть следующая рутина:TransactionScope и ошибка: ORA-02049

For j = 1 To NumItems 
    dbValueLookup.Load(j) 
    Using scope As New TransactionScope() 
     For i = firstIndex To lastIndex 

      'dbValueLookup is basically just a Dictionary of items already in the DB 
      If dbValueLookup.ContainsKey(i) Then 
       'updateData is a subroutine that updates this row with new data 
       updateData(j,i) 
       rowsUpdated = rowsUpdated + 1 
       dbValueLookup.Remove(i) 
      Else 
       'updateData is a subroutine that adds a new row to DB 
       addData(j,i) 
       rowsAdded = rowsAdded + 1 
      End If 
     Next 

     If dbValueLookup.Count = 0 Then 
      'This commits the transaction - records will be updated when End Using is reached 
      scope.Complete() 
      If rowsAdded + rowsUpdated > 0 Then 
       ShowMessage("Records Updated: " + rowsUpdated.ToString() + " Records Added: " + rowsAdded.ToString()) 
      End If 

     Else 
      'We are left with data from the database that was not updated. This is a problem, so we don't "Complete" the scope. 
      'This will result in a rollback. 
      ShowWarningMessage("Incomplete Data for " + i.ToString()) 
     End If 
    End Using 
Next 

Запуск этого как против нашего производства и тестирование базы данных Oracle 11g спорадически (или, если есть образец, я не нашел еще) генерирует Oracle Error: ORA-02049: таймаут: распределенная транзакция, ожидающая блокировки

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

Любые идеи, которые могут вызывать эту ошибку?

Заранее благодарен.

ответ

0

Итак, похоже, что у вас должно быть две транзакции, конкурирующие за блокировку строк.

Просто мозговой штурм, но если dbValueLookup.Count = 0, то вы будете называть addData (который звучит, как это делает INSERT?), Но вы не будете называть scope.Complete() совершить транзакцию.

Я не уверен, что End Using всегда будет совершать транзакцию или нет.

Вам действительно нужно создать TransactionScope на каждой итерации цикла? Почему бы не создать одну транзакцию, сделать все ваши обновления/вставки, а затем зафиксировать один раз?

Смежные вопросы