2011-05-09 72 views
1

已被執行我在交易中的桌面應用程序的提交收到此錯誤:事務錯誤提交()時,選擇內幕交易

這OleDbTransaction已完成;它不再可用。

我發現有類似的錯誤的其他職位表明,如果它需要很長時間或包含大量的數據,可能會發生這種情況。這裏不是這種情況。日誌記錄告訴我,從開始到提交需要140毫秒,並且在事務內部執行大約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,'[email protected]','FORSYNINGSLEDNINGER','vej 12','1700','Nyberg','NO','21491697',null,null,'[email protected]','051055f4-ea2a-4cb3-a016-6f6477e6a342','MUNCK FORSYNINGSLEDNINGER A/S','Jon Andersen','vej 38 B','7100','Vejle','NO',null,'23681515','76409220','[email protected]','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來運行並不是問題,但是如果您需要運行必須在事務內部運行的select,那該怎麼辦?

+0

對'BeginTransaction'的調用是否實際啓動了事務?代碼將異常記錄到日誌中,並且在該情況下不會引發錯誤。因此,代碼將繼續並在調用'Commit'時失敗。嘗試通過代碼來查看是否調用了'BeginTransaction'失敗。 – shahkalpesh 2011-05-10 07:16:28

+0

@shahkalpesh:日誌文件沒有報告任何錯誤。第一個錯誤是提交。如果它沒有真正開始事務,我會認爲'mConnection.BeginTransaction()'會返回'Nothing'而不是'OleDbTransaction'對象,對吧? – awe 2011-05-10 07:24:00

+0

@awe:你說得對。是否有任何'ExecuteSQL'語句失敗,這可能導致事務自行回滾? – shahkalpesh 2011-05-10 07:51:26

回答

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,但我試圖設置lCommand.Transaction = mTransaction上的選擇命令。當命令不是動作命令時,這顯然是不允許的。然而,這不是原始問題,因爲在我嘗試在select命令上設置活動事務之前,Commit上的錯誤在那裏。這只是我試圖修復它的方法而已。