VB OracleTransaction不回滚

时间:2010-09-14 09:29:33

标签: vb.net oracle transactions rollback

我正在从VB调用Oracle中的第三方存储过程,而不是回滚。

代码优先(我正在简化):

连接字符串:

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 个答案:

答案 0 :(得分:1)

PL / SQL中的提交/回滚逻辑(无论自主事务处理子句 - >除非您是错误记录,否则不要使用它: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发生时,插入之前所有INSERTS的内容。

如果希望VB应用程序处理事务,则必须从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 

/ *现在交易处于子子程序* /

答案 1 :(得分:0)

如果没有包装的来源,这个可能会很棘手。

对于初学者,如果在未使用AUTONOMOUS TRANSACTION编译指示标记的包内进行COMMIT或ROLLBACK,Oracle通常会引发异常,无论调用语言如何。

所以我假设如果包中包含COMMIT和ROLLBACK,那么包必须是自治的。 这意味着您的客户端回滚不会产生任何影响。

如果一个包是自治的,那么如果你在没有完成ROLLBACK或COMMIT的情况下退出包也会引发异常 - 即应该没有包可以退出的路由,在数据库上留下一个未提交的行。

可以解释你所看到的唯一情况是回滚是否失败,或者根本没有执行,然后代码继续执行COMMIT。

(另一种可能的选择 - Insert也是作为一个自治事务完成的,具有自包含的提交,以便在回滚之前提交数据?)。

自主交易因(重新) - 引入原子事务要避免的问题(竞争条件,数据完整性,死锁)而臭名昭着 - 它们有其用途,但必须小心处理。