VB OracleTransaction не отменяется - PullRequest
       18

VB OracleTransaction не отменяется

0 голосов
/ 14 сентября 2010

Я вызываю стороннюю хранимую процедуру в Oracle из VB, которая не откатывается.

Сначала код (я упрощаю):

Строка подключения:

String sqlstr = "SERVER=x.x.x.x;Database=db;uid=sa;pwd=admin;Connect Timeout=60; Min Pool Size=5; Max Pool Size=100;";

Вызов (я только что вызвал откат сразу после выполнения, чтобы проверить его):

Dim Oraclecon As New OracleConnection(_OracleConnection)
Dim sqlCon As New SqlConnection(_SQLConnection)
Dim oTrans As OracleTransaction = Nothing

 Oraclecon.Open()
 oTrans = Oraclecon.BeginTransaction()
 Dim myCMD As New OracleCommand()
 myCMD.Connection = Oraclecon
 myCMD.Transaction = oTrans
 myCMD.CommandText = "CREATE_USER"
 myCMD.CommandType = CommandType.StoredProcedure
 myCMD.Parameters.Add(New OracleParameter("username", OracleType.VarChar)).Value = UserName
 myCMD.Parameters.Add(New OracleParameter("passwd", OracleType.VarChar)).Value = Password
 myCMD.Parameters.Add(New OracleParameter("speed", OracleType.VarChar)).Value = Speed
 myCMD.Parameters.Add(New OracleParameter("monthly_quota", OracleType.VarChar)).Value = Quota
 myCMD.Parameters.Add(New OracleParameter("type", OracleType.VarChar)).Value = "H"
 Dim oparam As OracleParameter
 oparam = New OracleParameter("success_flag", OracleType.VarChar)
 oparam.Size = 1
 oparam.Direction = ParameterDirection.Output

 Dim oparam2 As OracleParameter
 oparam2 = New OracleParameter("err_msg", OracleType.VarChar)
 oparam2.Direction = ParameterDirection.Output
 oparam2.Size = 100

 myCMD.Parameters.Add(oparam)
 myCMD.Parameters.Add(oparam2)

 Dim RowId As OracleString

 myCMD.ExecuteOracleNonQuery(RowId)
 oTrans.Rollback()

Я не могу дать подробную информацию о хранимой процедуре, но она выполняет коммит иоткат внутри него.

В любом случае выполняется вставка, и этот немедленный откат не откатывает вставку.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 14 сентября 2010

Логика фиксации / отката в PL / SQL (независимо от условия AUTONOMOUS TRANSACTION -> НЕ ИСПОЛЬЗУЙТЕ ЭТО, если вы не ведете журнал ошибок: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2212445691154)

Итак, если вы отправите COMMIT в вашем пакете, ваши данные будут переданы, PERIOD. Откатить так же.

Создать таблицу для следующих примеров:

create  table SHOW_TRANSACTION (MISC varchar2(15)) ;
/

Глядя на этот пример, видно, что:

declare

   procedure DOTHEINSERT(DATAM in SHOW_TRANSACTION.MISC%type ,
                        doCommit IN boolean

   ) 
   as
   begin    
            insert into SHOW_TRANSACTION (MISC) 
            values (DATAM);

            if DOCOMMIT   then
               commit ;
            else
               ROLLBACK ;
            end if;
   end ;
begin
    DOTHEINSERT('commit1' , true);
    DOTHEINSERT('NOcommit1' , false);
    DOTHEINSERT('commit2' , true);
    DOTHEINSERT('NOcommit2' , false);
    DOTHEINSERT('commit3' , true);
    ROLLBACK;


end ;
/

select * from SHOW_TRANSACTION ;
/
MISC            
--------------- 
commit1         
commit2         
commit3   

Обратите внимание, что окончательный ROLLBACK ничего не делает? это потому, что COMMIT / ROLLBACKS в процедуре влияют на всю область видимости, посмотрите на этот пример:

truncate table SHOW_TRANSACTION; --start with clean slate

declare

   procedure DOTHEINSERT(DATAM in SHOW_TRANSACTION.MISC%type ,
                        doCommit IN boolean

   ) 
   as
   begin    
            insert into SHOW_TRANSACTION (MISC) 
            values (DATAM);

            if DOCOMMIT   then
               commit ;
            --else (HERE I AM GETTING RID OF THE PROCEDURES ROLLBACK, SO EVERYTHING IS BEING ROLLBACK'ED
            --   ROLLBACK ;

            end if;
   end ;
begin
    DOTHEINSERT('commit1' , true);
    DOTHEINSERT('NOcommit1' , false);
    DOTHEINSERT('commit2' , true);
    DOTHEINSERT('NOcommit2' , false);
    DOTHEINSERT('commit3' , true);
    ROLLBACK;


end ;
/

select * from SHOW_TRANSACTION ;
/

MISC            
--------------- 
commit1         
NOcommit1       
commit2         
NOCOMMIT2       
commit3     

Здесь пакет ROLLBACK удаляется, поэтому, когда происходит этот COMMIT, содержимое всех вставок до этого вставляется.

Если вы хотите, чтобы приложение VB обрабатывало транзакцию, вы должны удалить commit / rollback из PL / SQL.

Кроме того, не имеет значения, где находится фиксация / откат, они указывают на ВЕСЬ ОБЪЕМ всех элементов транзакции:

truncate table SHOW_TRANSACTION ; 

declare

   procedure DOTHEINSERT(DATAM in SHOW_TRANSACTION.MISC%type ,
                        doCommit IN boolean

   ) 
   as
          procedure DOTHETRANSACTION(doCommit IN boolean) as 
          begin
            if DOCOMMIT   then
               commit ;
            else -- (HERE I AM GETTING RID OF THE PROCEDURES ROLLBACK, SO EVERYTHING IS BEING ROLLBACK'ED
               ROLLBACK ;
            end if;             
          END DOTHETRANSACTION;
   begin    
            insert into SHOW_TRANSACTION (MISC) 
            values (DATAM);
            DOTHETRANSACTION(doCommit);
   end DOTHEINSERT;
begin
    DOTHEINSERT('commit1' , true);
    DOTHEINSERT('NOcommit1' , false);
    DOTHEINSERT('commit2' , true);
    DOTHEINSERT('NOcommit2' , false);
    DOTHEINSERT('commit3' , true);
    ROLLBACK;


end ;
/

select * from SHOW_TRANSACTION ;
/

MISC            
--------------- 
commit1         
COMMIT2         
commit3 

/ * теперь транзакция находится в подпрограмме sub / sub * /

0 голосов
/ 14 сентября 2010

Без источника пакета этот может быть сложным.

Для начала Oracle обычно вызывает исключение, если вы делаете COMMIT или ROLLBACK внутри пакета, который не помечен прагмой AUTONOMOUS TRANSACTION, независимо от того,языка вызова.

Так что я предполагаю, что если пакет содержит COMMIT и ROLLBACK, то пакет ДОЛЖЕН быть автономным.Это будет означать, что откат на стороне клиента не окажет никакого влияния.

Если пакет является автономным, то возникает исключение, если вы выходите из пакета без выполнения ROLLBACK или COMMIT - т.е. не должно быть никакихмаршрут, по которому пакет мог бы выйти, оставив незафиксированную строку в базе данных.

Единственная ситуация, которая могла бы объяснить то, что вы видите, это если откат ОТКАЗАЛ, или не был выполнен вообще, и код затем выполняетсяCOMMIT.

(Еще один возможный вариант - вставка также выполнялась как автономная транзакция с автономной фиксацией, чтобы данные были зафиксированы до отката?).

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

...