嗨,我对ADO.net中的交易感到生气,
我想做什么:我的数据集中的所有更改,使用Update方法执行,在事务中执行 - 这很好,但是我需要通过SQL查询执行其他sql命令仍然是一个事务。我的代码是按照良好的提示编写的,如果任何命令失败,则try-catch阻止我回滚整个事务,如果正确的错误提交更改,则 - >这恰好适用于通过Update方法执行的命令,因为当我通过executeNonQuery执行时,当我观察数据库中的更改时立即进行更改...根据所有指导我看到了两种方法如何在数据集内和executeNonQuery中使用事务命令,但没有发现它们的任何组合或这种方法的任何问题,任何想法?
严重的整个代码不是英文的,并且很长,事务经历了几次更新,没关系,我希望我们得到问题的核心......这里是代码:
'这是应该在一个事务中完成所有表的整个更新,插入和删除的主要方法
Public Sub DSdoDBOtazkyAdotaznikINSERT_UPDATE_DELETE()
'vytvoření zálohy
Zaloha.vytvorZalohu(My.Settings.RecentDatabasedUsed, False, True)
Try
'Priprava Transakce
SpojeniS_DB_TRANSAKCNI.Open()
Catch ex As Exception
Throw ex
Exit Sub
End Try
Dim QtionAQnnaireTransaction As System.Data.OleDb.OleDbTransaction
QtionAQnnaireTransaction = Me.SpojeniS_DB_TRANSAKCNI.BeginTransaction(IsolationLevel.ReadCommitted)
'1, Update Commandy
QstionUpdateCommand.Transaction = QtionAQnnaireTransaction
CategoryUpdateCommand.Transaction = QtionAQnnaireTransaction
CategoryDefUpdateCommand.Transaction = QtionAQnnaireTransaction
CCheckUpdateCommand.Transaction = QtionAQnnaireTransaction
BatteryItemUpdateCommand.Transaction = QtionAQnnaireTransaction
ChecKUpdateCommand.Transaction = QtionAQnnaireTransaction
TextFillUpdateCommand.Transaction = QtionAQnnaireTransaction
RowUpdateCommand.Transaction = QtionAQnnaireTransaction
ProgramCodeupdateCommand.Transaction = QtionAQnnaireTransaction
DotaznikyVsechnyUpdateCommand.Transaction = QtionAQnnaireTransaction
'2, Insert Commandy
QstionInsertCommand.Transaction = QtionAQnnaireTransaction
CategoryInsertCommand.Transaction = QtionAQnnaireTransaction
CategoryDefInsertCommand.Transaction = QtionAQnnaireTransaction
CCheckInsertCommand.Transaction = QtionAQnnaireTransaction
BatteryItemInsertCommand.Transaction = QtionAQnnaireTransaction
ChecKInsertCommand.Transaction = QtionAQnnaireTransaction
TextFillInsertCommand.Transaction = QtionAQnnaireTransaction
RowInsertCommand.Transaction = QtionAQnnaireTransaction
ProgramCodeInsertCommand.Transaction = QtionAQnnaireTransaction
DotaznikVsechnyInsertCommand.Transaction = QtionAQnnaireTransaction
'3, Delete Commandy
QstionDeleteCommand.Transaction = QtionAQnnaireTransaction
DotaznikVsechDeleteCommand.Transaction = QtionAQnnaireTransaction
'ostatní DELETE commandy přiřazení do transakcí nalezneme v metodě DBpripravDatatableNaZapisDatS_PosunutimPK
'CategoryDeleteCommand.Transaction = QtionAQnnaireTransaction
'CategoryDefDeleteCommand.Transaction = QtionAQnnaireTransaction
'CCheckDeleteCommand.Transaction = QtionAQnnaireTransaction
'BatteryItemDeleteCommand.Transaction = QtionAQnnaireTransaction
'ChecKDeleteCommand.Transaction = QtionAQnnaireTransaction
'TextFillDeleteCommand.Transaction = QtionAQnnaireTransaction
'RowDeleteCommand.Transaction = QtionAQnnaireTransaction
'ProgramCodeDeleteCommand.Transaction = QtionAQnnaireTransaction
Dim slovnikProPrvotniUpdate As New Dictionary(Of DataRow, Double)
Try
'nastaveni spojeni vsem commandum spojeni
Me.nastaveniPripojeniNaUDIprikazy(Me.SpojeniS_DB_TRANSAKCNI)
'1, QUESTION
'!!!!! důležitá záloha datasetu
zalohujDataset()
'DELETE otázek
DATAdapter.DeleteCommand = QstionDeleteCommand
DATAdapter.Update(DStabulkaOtazek.Select("MotherQReference is NOT NULL", Nothing, DataViewRowState.Deleted))
DATAdapter.Update(DStabulkaOtazek.Select("MotherQReference is NULL", Nothing, DataViewRowState.Deleted))
'UPDATE otázek
'potřeba řešit pořadí UPDATOVANÝCH OTÁZEK - problémová situace: pokud dojde k změbě pořadí otázky - tedy PK otázky se uvolní a posléze PK nové otázky nebo jiné updatované otázky bude nastaven na PK předešlé otázky, která již PK nemá -
'druhým problémem je pokud si dvě otázky "vymění PK", proto nejprve všem UPDATOVANÝM otázkám změníme UPDATOVANÝ PK na temporární - insertu uvolníme místo vložení a updatované otázky se zbaví zabraných
DATAdapter.UpdateCommand = QstionUpdateCommand
slovnikProPrvotniUpdate = DStabulkaOtazek.PRIPRAVAUPDATEzmenaPoradiaPKproUPDATE()
'exekuce řádků pro nastavení Temporárních změn Update
'hlavní otázka UPDATE - musí jít první kvůli kaskádě
DATAdapter.Update(slovnikProPrvotniUpdate.Keys.Cast(Of DataRow).Where(Function(x) IsDBNull(x.Item("MotherQReference"))).ToArray)
'podotázek otázka UPDATE - musí jít první kvůli kaskádě
DATAdapter.Update(slovnikProPrvotniUpdate.Keys.Cast(Of DataRow).Where(Function(x) Not IsDBNull(x.Item("MotherQReference"))).ToArray)
'InsertCommandProQuestion
DATAdapter.InsertCommand = QstionInsertCommand
DATAdapter.Update(DStabulkaOtazek.Select(Nothing, Nothing, DataViewRowState.Added))
'vrácení původních řádků - již zpětně změny
DStabulkaOtazek.UNDOakceNaUpdate(slovnikProPrvotniUpdate)
'hlavní otázka UPDATE - musí jít první kvůli kaskádě
DATAdapter.Update(slovnikProPrvotniUpdate.Keys.Cast(Of DataRow).Where(Function(x) IsDBNull(x.Item("MotherQReference"))).ToArray)
'podotázek otázka UPDATE - musí jít první kvůli kaskádě
DATAdapter.Update(slovnikProPrvotniUpdate.Keys.Cast(Of DataRow).Where(Function(x) Not IsDBNull(x.Item("MotherQReference"))).ToArray)
'2, BATTERYITEM
Me.DBpripravDatatableNaZapisDatS_PosunutimPK(DStabulkaBaterii, QtionAQnnaireTransaction)
'InsertCommand pro BatteryItem
DATAdapter.InsertCommand = BatteryItemInsertCommand
'UpdateCommand pro BatteryItem
DATAdapter.UpdateCommand = BatteryItemUpdateCommand
'Execute Commandu pro BatteryItem
DATAdapter.Update(DSaplikace.Tables.Item("BatteryItem"))
'3, CATEGORY
Me.DBpripravDatatableNaZapisDatS_PosunutimPK(DStabulkaKategorii, QtionAQnnaireTransaction)
'InsertCommand pro CATEGORY
DATAdapter.InsertCommand = CategoryInsertCommand
'UpdateCommand pro CATEGORY
DATAdapter.UpdateCommand = CategoryUpdateCommand
'Execute Commandu pro CATEGORY
DATAdapter.Update(DSaplikace.Tables.Item("CATEGORY"))
'4, PROGRAMCODE
Me.DBpripravDatatableNaZapisDatS_PosunutimPK(DSaplikace.Tables.Item("ProgramCode"), QtionAQnnaireTransaction)
'InsertCommand pro ProgramCode
DATAdapter.InsertCommand = ProgramCodeInsertCommand
'UpdateCommand pro ProgramCode
DATAdapter.UpdateCommand = ProgramCodeupdateCommand
'DeleteCommand pro ProgramCode
DATAdapter.Update(DSaplikace.Tables.Item("ProgramCode"))
'5, ROW
Me.DBpripravDatatableNaZapisDatS_PosunutimPK(DStabulkaRadkyTababulky, QtionAQnnaireTransaction)
'InsertCommand pro row
DATAdapter.InsertCommand = RowInsertCommand
'UpdateCommand pro row
DATAdapter.UpdateCommand = RowUpdateCommand
DATAdapter.Update(DSaplikace.Tables.Item("row"))
'6, TEXTFILL
Me.DBpripravDatatableNaZapisDatS_PosunutimPK(DStabulkaDynText, QtionAQnnaireTransaction)
'InsertCommand pro textfill
DATAdapter.InsertCommand = TextFillInsertCommand
'UpdateCommand pro textfill
DATAdapter.UpdateCommand = TextFillUpdateCommand
'DeleteCommand pro textfill
DATAdapter.Update(DSaplikace.Tables.Item("textfill"))
'7, CHECK
Me.DBpripravDatatableNaZapisDatS_PosunutimPK(DStabulkaKontrol, QtionAQnnaireTransaction)
'InsertCommand pro CHECK
DATAdapter.InsertCommand = ChecKInsertCommand
'UpdateCommand pro CHECK
DATAdapter.UpdateCommand = ChecKUpdateCommand
DATAdapter.Update(DSaplikace.Tables.Item("CHECK"))
'8, CategoryDefinition definition
' Me.DBpripravDatatableNaZapisDatS_PosunutimPK(DStabulkaDefinicKategorii, QtionAQnnaireTransaction, Me.SpojeniS_DB)
'InsertCommand pro CategoryDefinition
DATAdapter.InsertCommand = CategoryDefInsertCommand
'UpdateCommand pro CategoryDefinition
' DATAdapter.UpdateCommand = CategoryDefUpdateCommand
DATAdapter.Update(DSaplikace.Tables.Item("CategoryDef"))
'10, Questionnaire - Update
DotaznikyVsechnyUpdateCommand.Connection = SpojeniS_DB_TRANSAKCNI
DotaznikVsechDeleteCommand.Connection = SpojeniS_DB_TRANSAKCNI
DotaznikVsechnyInsertCommand.Connection = SpojeniS_DB_TRANSAKCNI
DATAdapter.UpdateCommand = DotaznikyVsechnyUpdateCommand
DATAdapter.Update(DSaplikace.Tables.Item("Questionnaire"))
QtionAQnnaireTransaction.Commit()
Catch ex As Exception
undoDatDatasetu()
QtionAQnnaireTransaction.Rollback()
Throw ex
Finally
SpojeniS_DB_TRANSAKCNI.Close()
End Try
End Sub
这个方法应该有executeNoQuery - 在事务中删除命令,从上面的方法调用几次,因为我运行语句executeNonQuery(但应该在事务中),数据库接受更改
Private Sub DBpripravDatatableNaZapisDatS_PosunutimPK(ByVal DT As DTCapi, ByVal transakce As OleDb.OleDbTransaction)
'smažeme všechny řádky kontrol v DB k jedné otázce, pokud
'došlo k Insertu nebo k Deletu alespoň jedné kontroly
Dim HashSetPKotazekKontrolnaSmazani As New HashSet(Of String)
Dim dtv As New DataView(DT)
dtv.RowStateFilter = DataViewRowState.Added + DataViewRowState.Deleted
For Each drv As DataRowView In dtv
HashSetPKotazekKontrolnaSmazani.Add(drv("IDQnnaireQOrderQOrderMother"))
Next
'smazání řádků v DB
For Each PKotazky As String In HashSetPKotazekKontrolnaSmazani
Dim deleteCMD As New OleDb.OleDbCommand("DELETE FROM [" + DT.TableName + "] where IDQnnaireQOrderQOrderMother= ?")
'nastavení parametru
Dim parametrProSmazani As New OleDbParameter
parametrProSmazani.Value = PKotazky
' HERE IS DELETE within transaction
deleteCMD.Transaction = transakce
deleteCMD.Connection = transakce.Connection
deleteCMD.Parameters.Add(parametrProSmazani)
'when following statement i call this changes in DB are done, no matter in didnt commited...transaction
deleteCMD.ExecuteNonQuery()
Next
'odstranění z DT delete řádků
Dim radkyNaSmazani As DataRow() = DT.Select(DataViewRowState.Deleted)
For Each radek As DataRow In radkyNaSmazani
DT.Rows.Remove(radek)
Next
'u všech řádků otázek, jejiž kontroly jsme vymazali v DB nastavíme v DT stav added
Dim vyberovyRetezec As String = CDfunkce.ADOdtSelectRETEZECor("IDQnnaireQOrderQOrderMother", HashSetPKotazekKontrolnaSmazani)
If vyberovyRetezec <> "" Then
Dim radkyProOznaceniJakoPridane As DataRow() = DT.Select(vyberovyRetezec)
'nastavení řádků Added
For Each radek As DataRow In radkyProOznaceniJakoPridane
If radek.RowState <> DataRowState.Added Then
radek.AcceptChanges()
radek.SetAdded()
End If
Next
End If
End Sub