TransactionScope.Dispose Methode
Definition
Wichtig
Einige Informationen beziehen sich auf Vorabversionen, die vor dem Release ggf. grundlegend überarbeitet werden. Microsoft übernimmt hinsichtlich der hier bereitgestellten Informationen keine Gewährleistungen, seien sie ausdrücklich oder konkludent.
Beendet den Transaktionsbereich.
public:
virtual void Dispose();
public void Dispose ();
abstract member Dispose : unit -> unit
override this.Dispose : unit -> unit
Public Sub Dispose ()
Implementiert
Beispiele
Im folgenden Beispiel wird veranschaulicht, wie Die TransactionScope -Klasse verwendet wird, um einen Codeblock zu definieren, der an einer Transaktion teilnimmt.
// This function takes arguments for 2 connection strings and commands to create a transaction
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
// transaction is rolled back. To test this code, you can connect to two different databases
// on the same server by altering the connection string, or to another 3rd party RDBMS by
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
{
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
try
{
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
' This function takes arguments for 2 connection strings and commands to create a transaction
' involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
' transaction is rolled back. To test this code, you can connect to two different databases
' on the same server by altering the connection string, or to another 3rd party RDBMS
' by altering the code in the connection2 code block.
Public Function CreateTransactionScope( _
ByVal connectString1 As String, ByVal connectString2 As String, _
ByVal commandText1 As String, ByVal commandText2 As String) As Integer
' Initialize the return value to zero and create a StringWriter to display results.
Dim returnValue As Integer = 0
Dim writer As System.IO.StringWriter = New System.IO.StringWriter
Try
' Create the TransactionScope to execute the commands, guaranteeing
' that both commands can commit or roll back as a single unit of work.
Using scope As New TransactionScope()
Using connection1 As New SqlConnection(connectString1)
' Opening the connection automatically enlists it in the
' TransactionScope as a lightweight transaction.
connection1.Open()
' Create the SqlCommand object and execute the first command.
Dim command1 As SqlCommand = New SqlCommand(commandText1, connection1)
returnValue = command1.ExecuteNonQuery()
writer.WriteLine("Rows to be affected by command1: {0}", returnValue)
' If you get here, this means that command1 succeeded. By nesting
' the using block for connection2 inside that of connection1, you
' conserve server and network resources as connection2 is opened
' only when there is a chance that the transaction can commit.
Using connection2 As New SqlConnection(connectString2)
' The transaction is escalated to a full distributed
' transaction when connection2 is opened.
connection2.Open()
' Execute the second command in the second database.
returnValue = 0
Dim command2 As SqlCommand = New SqlCommand(commandText2, connection2)
returnValue = command2.ExecuteNonQuery()
writer.WriteLine("Rows to be affected by command2: {0}", returnValue)
End Using
End Using
' The Complete method commits the transaction. If an exception has been thrown,
' Complete is called and the transaction is rolled back.
scope.Complete()
End Using
Catch ex As TransactionAbortedException
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message)
End Try
' Display messages.
Console.WriteLine(writer.ToString())
Return returnValue
End Function
Hinweise
Das Aufrufen dieser Methode markiert das Ende des Transaktionsbereichs. Wenn das TransactionScope Objekt die Transaktion erstellt und Complete im Bereich aufgerufen wurde, versucht das TransactionScope Objekt, die Transaktion zu committen, wenn diese Methode aufgerufen wird. In diesem Fall blockiert diese Methode, bis die erste Phase der Transaktionsverarbeitung abgeschlossen ist. Die erste Phase endet, nachdem alle Ressourcenmanager und Enlists in der Transaktion über das Transaktionsergebnis abgestimmt haben und der TransactionManager sich dauerhaft entschieden hat, die Transaktion zu verpflichten oder abzubrechen. Die zweite Phase der Verarbeitung ist immer asynchron. Daher gibt es keine Garantie dafür, dass Daten, die nur aus einer bestimmten Transaktion stammen, sofort verfügbar sind, wenn keine andere Transaktion zum Anzeigen dieser Daten verwendet wird.
Die Verwendung der C#- using
Konstruktion stellt sicher, dass diese Methode aufgerufen wird, auch wenn eine Ausnahme auftritt. Ausnahmen, die nach dem Aufrufen dieser Methode eintreten, beeinflussen die Transaktion möglicherweise nicht. Mit dieser Methode wird auch die Umgebungstransaktion im ursprünglichen Zustand wiederhergestellt. Ein TransactionAbortedException wird ausgelöst, wenn die Transaktion nicht tatsächlich committet wird.
Da diese Methode blockiert wird, bis die erste Phase der Transaktionsverarbeitung abgeschlossen ist, sollten Sie bei verwendung dieser Methode in einer Windows Form-Anwendung (WinForm) äußerst vorsichtig sein, da es zu einem Deadlock kommen kann. Wenn Sie diese Methode innerhalb eines WinForm-Steuerelementereignisses aufrufen (z. B. durch Klicken auf eine Schaltfläche), und verwenden Sie die synchrone Invoke Methode, um das Steuerelement zur Ausführung einiger Ui-Aufgaben (z. B. Ändern von Farben) in der Mitte der Verarbeitung der Transaktion anzuweisen, tritt ein Deadlock auf. Dies liegt daran, dass die Invoke Methode synchron ist und den Workerthread blockiert, bis der UI-Thread seinen Auftrag abgeschlossen hat. In unserem Szenario wartet der UI-Thread jedoch auch darauf, dass der Workerthread die Transaktion committet. Das Ergebnis ist, dass keiner fortfahren kann und der Bereich unbegrenzt wartet, bis der Commit abgeschlossen ist. Sie sollten BeginInvoke es verwenden, anstatt Invoke wo immer möglich, da es asynchron und somit weniger anfällig für Deadlocks ist.
Weitere Informationen zur Verwendung dieser Methode finden Sie im Thema Implementieren einer impliziten Transaktion mithilfe des Transaktionsbereichs .