在事务内部执行select时调用Commit()时发生事务错误

时间:2011-05-09 13:16:29

标签: vb.net ado.net transactions

我在桌面应用程序的事务提交中遇到此错误:

  

这个OleDbTransaction已经完成;它不再可用了。

我见过的其他类似错误的帖子表明,如果需要很长时间或包含大量数据,就会发生这种情况。这不是这种情况。记录告诉我从Begin到Commit需要140 ms,在事务中执行大约10个命令。

它正在使用Oracle数据库。

此类是我的数据库类的简化版本:

Class MyDatabase 
Private mConnection AS OleDbConnection
Private mTransaction AS OleDbTransaction

Function Value(ByVal piSql As String) As Integer
  Try
    Dim lCommand As OleDbCommand
    lCommand = New OleDbCommand(piSql, mConnection)
    If mTransaction IsNot Nothing Then
        lCommand.Transaction = mTransaction
    End If
    Dim lValue = lCommand.ExecuteScalar()
    If Not lValue Is Nothing Then
      WriteLog(lValue.ToString(), 3, "Value Returned")
      Return lValue.ToString()
    Else
      WriteLog("<null>", 3, "Value Returned (null)")
      Return ""
    End If
  Catch ex As Exception
      WriteLog(ex.Message)
  End Try
End Function
Function ExecuteSql(ByVal piSql As String) As Integer
  Try
    Dim lCommand As OleDbCommand
    lCommand = New OleDbCommand(piSql, mConnection)
    If mTransaction IsNot Nothing Then
      lCommand.Transaction = mTransaction
    End If
    Return lCommand.ExecuteNonQuery()
  Catch ex As Exception
    WriteLog(ex.Message)
  End Try
End Function

Public Sub BeginTransaction()
  Try
    mTransaction = mConnection.BeginTransaction()
  Catch ex As Exception
    WriteLog(ex.Message)
  End Try
End Sub

Public Sub Commit()
  If Not mTransaction Is Nothing Then
    Try
      mTransaction.Commit()
    Catch ex As Exception
      WriteLog(ex.Message)
    End Try
    mTransaction.Dispose()
    mTransaction = Nothing
  End If
End Sub

Public Sub Rollback()
  If Not mTransaction Is Nothing Then
    Try
      mTransaction.Rollback()
    Catch ex As Exception
      WriteLog(ex.Message)
    End Try
    mTransaction.Dispose()
    mTransaction = Nothing
  End If
End Sub

End Class

调用代码(简化):

mDatabase.BeginTransaction()
mOrderId = mDatabase.Value("select max(order_id) from ler_order")
mDatabase.ExecuteSql("insert into ler_order (order_id,status,message,plotter,reference,paper_size,orientation,plot_scale,format,usr,email,no_of_copies,date_time,uservar1,uservar2,uservar3,ell,nll,eur,nur,coord_type,graveforespoergselanmodningid,graveforespoergselnr,oprettetdato,aendretdato,graveartnavn,andengraveart,lek_virksomhed,lek_navn,lek_adresse,lek_postnr,lek_postdistrikt,lek_land,lek_telefon,lek_mobiltelefon,lek_telefax,lek_email,ga_navn,ga_adresse,ga_postnr,ga_postdistrikt,ga_land,ga_telefon,ga_mobiltelefon,ga_telefax,ga_email,gak_id,gak_virksomhed,gak_navn,gak_adresse,gak_postnr,gak_postdistrikt,gak_land,gak_telefon,gak_mobiltelefon,gak_telefax,gak_email,emailafsendt,konverteringsstatus)  values (101633,0,null,'LER','10d6d8bc-b9b2-44bb-84bf-ceca42a0970a',null,0,0,null,null,null,0,'09-05-2011 13:25:33',null,null,'VAND',-259954.967,145092.123,-259802.657,145147.225,1,'10d6d8bc-b9b2-44bb-84bf-ceca42a0970a',425950,'09-05-2011 13:20:27','09-05-2011 13:20:58','Gravemaskine',null,null,'Ledningsoplysning','Kokbjerg',null,'Kolding',null,'59 23 44 55',null,null,'info@mail.com','FORSYNINGSLEDNINGER','vej 12','1700','Nyberg','NO','21491697',null,null,'mail@info.com','051055f4-ea2a-4cb3-a016-6f6477e6a342','MUNCK FORSYNINGSLEDNINGER A/S','Jon Andersen','vej 38 B','7100','Vejle','NO',null,'23681515','76409220','mail@info.com','09-05-2011 13:20:58','OK')")
mDatabase.ExecuteSql("delete from ler_order_coord where order_id = 101633")
mDatabase.ExecuteSql("insert into ler_order_coord (order_id,polygon_no,seq_no,east,north)  values (101633,1,1,-259954.967,145120.599)")
mDatabase.ExecuteSql("insert into ler_order_coord (order_id,polygon_no,seq_no,east,north)  values (101633,1,2,-259951.933,145092.123)")
mDatabase.ExecuteSql("insert into ler_order_coord (order_id,polygon_no,seq_no,east,north)  values (101633,1,3,-259802.657,145111.956)")

mDatabase.Commit() 'This is where the error occurs

修改 有关我如何解决这个问题,请参阅my answer 我有一个关于此的后续问题:是否不允许在这样的事务中运行select?或者可以通过在特定隔离级别运行事务来完成(我看到BeginTransaction方法有一个可选参数来执行此操作)? ..还是其他一些解决方案..?在我的情况下,在事务开始之前将select移动到运行并不是一个问题,但是如果你需要运行必须在事务中运行的选择呢?

1 个答案:

答案 0 :(得分:0)

我找到了另一个问题的答案,这对我一路走来: How to check if Dotnet transaction is rolled back?

我实现了TransactionScope以更好地控制我的事务,我注意到日志中有一条新的错误消息:

  

交易管理器不可用。 (来自HRESULT的异常:0x8004D01B)

在select语句中触发了此错误:

mOrderId = mDatabase.Value("select max(order_id) from ler_order")

我在事务开始之前将选择移动到了现在它的工作原理!

修改
我发现触发此错误的原因可能不是TransactionScope的使用,而是我尝试在select命令上设置lCommand.Transaction = mTransaction。当命令不是动作命令时,显然不允许这样做。然而,这不是原始问题,因为在我尝试在select命令上设置活动事务之前,Commit上的错误已存在。这只是我尝试修复它的方法。