Ich versuche, Transaktionen in meiner Anwendung zu implementieren. Ich versuche nur, es wie im Beispiel in der BeginTransaction () -Dokumentation zu implementieren .
Public Shared Sub Process(wwid As String, trade_id As Integer, disposition As Boolean)
Dim q As String
Dim cmd, cmd_select As SqlCommand
Dim reader As SqlDataReader
Dim trans As SqlTransaction
Dim user_id As Integer = User.CheckAuthentication(wwid)
If user_id > 0 Then
Using conn As New SqlConnection(CNGDB)
conn.Open()
'1. ReadUncommitted
'2. ReadCommitted
'3. RepeatableRead
'4. Serializable
'5. Snapshot
trans = conn.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted)
Try
q = "UPDATE Trades SET Disposition = @disposition, FinalizedAt = @finalized_at" & _
" WHERE TradeID = @trade_id"
cmd = New SqlCommand(q, conn)
cmd.Transaction = trans
cmd.Parameters.AddWithValue("@disposition", disposition)
cmd.Parameters.AddWithValue("@finalized_at", DateTime.Now)
cmd.Parameters.AddWithValue("@trade_id", trade_id)
cmd.ExecuteNonQuery()
If disposition = True Then
q = "SELECT Ownership_OwnershipID, Recipient_UserID FROM Trades" & _
" WHERE TradeID = @trade_id"
cmd_select = New SqlCommand(q, conn)
cmd_select.Transaction = trans
cmd_select.Parameters.AddWithValue("@trade_id", trade_id)
reader = cmd_select.ExecuteReader
reader.Read()
q = "UPDATE Ownerships SET User_UserID = @recipient_id" & _
" WHERE OwnershipID = @ownership_id"
cmd = New SqlCommand(q, conn)
cmd.Transaction = trans
cmd.Parameters.AddWithValue("@recipient_id", reader("Recipient_UserID"))
cmd.Parameters.AddWithValue("@ownership_id", reader("Ownership_OwnershipID"))
cmd.ExecuteNonQuery()
End If
trans.Commit()
Catch ex As Exception
Console.WriteLine("Commit Exception Type: {0}", ex.GetType())
Console.WriteLine(" Message: {0}", ex.Message)
Try
trans.Rollback()
Catch ex2 As Exception
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType())
Console.WriteLine(" Message: {0}", ex2.Message)
End Try
End Try
End Using
End If
End Sub
Das Problem ist, dass ich immer dann, wenn es auf Commit () trifft, den Fehler bekomme:
Commit-Ausnahmetyp: System.Data.SqlClient.SqlException
Nachricht: Die Transaktionsoperation kann nicht ausgeführt werden, da an dieser Transaktion ausstehende Anforderungen arbeiten.
Ich gehe davon aus, dass das Problem in der Tatsache liegt, dass ich versuche, aus dem zu lesen SELECT
, um die Werte in der Sekunde zu füllen UPDATE
, aber ich weiß nicht, wie es sonst gemacht werden kann. Ich habe versucht, die Datenbank IsolationLevel auf einige andere Werte zu setzen, und es ändert sich nichts.
Ich habe auch die TransactionScope- Klasse gefunden und ihr Beispiel für diesen Code implementiert. Als ich jedoch versuchte, diese Technik auf eine kompliziertere Gruppe von Vorgängen anzuwenden, wurde beanstandet, dass sie nicht mit dem Distributed Transaction Server meines lokalen Computers kommunizieren konnte. Ich schaltete es ein und das DTS stornierte diese andere, kompliziertere Transaktion aus einem nicht näher bezeichneten Grund, und ich wollte nicht in dieses Kaninchenloch gehen.
Kann jemand darauf hinweisen, was ich in meinem Code falsch mache?
Was ist der richtige Weg, um eine Reihe von SQL-Operationen in ein .NET-Programm zu verpacken? Vielleicht ist DTS der bessere Weg, aber diese Anwendung wird irgendwann in einer Azure-Datenbank gespeichert, und Azure scheint DTS ohnehin nicht zu unterstützen, obwohl es einige Ausdrücke über die "automatische Eskalation" von Isolationsstufen gibt, und ich bin verwirrt .
Ich habe in dieser Anwendung aus Gründen der Geschwindigkeit kurz mit gespeicherten Prozeduren gespielt, aber festgestellt, dass sie nicht schneller sind, und beschlossen, dass ich nicht versuchen möchte, Code in der Datenbank zu verwalten. Vielmehr wollte ich meine Datenbankzugriffsbibliothek in Visual Studio zusammen mit meiner GUI-Front-End-Anwendung (in VB) behalten, um (meistens) an einem Ort daran arbeiten zu können.