Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Třída CommittableTransaction poskytuje explicitní způsob, jak aplikace používat transakci, nikoli použití TransactionScope třídy implicitně. Je užitečné pro aplikace, které chtějí použít stejnou transakci napříč více voláními funkce nebo více voláními vlákna. Na rozdíl od třídy musí autor aplikace přímo volat metody TransactionScope a Commit pro potvrzení nebo zrušení transakce.
Přehled třídy CommittableTransaction
Třída CommittableTransaction je odvozena od Transaction třídy, a proto poskytuje všechny funkce druhé. Konkrétně je užitečná Rollback metoda třídy Transaction , která se dá použít také k vrácení objektu CommittableTransaction zpět.
Třída Transaction je podobná CommittableTransaction třídě, ale nenabízí metodu Commit . To vám umožní předat objekt transakce (nebo klony) jiným metodám (potenciálně v jiných vláknech), zatímco stále řídí, kdy transakce je potvrzena. Volaný kód je schopen začlenit a hlasovat o transakci, ale pouze tvůrce CommittableTransaction objektu má schopnost potvrdit transakci.
Při práci s CommittableTransaction třídou byste měli poznamenat následující:
Vytvoření CommittableTransaction transakce nenastavuje probíhající transakci. Potřebujete konkrétně nastavit a resetovat okolí transakce, aby správci prostředků fungovali ve správném kontextu transakce, pokud je to vhodné. Způsob, jak nastavit aktuální tranzakce prostředí, je nastavením statické Current vlastnosti na globální Transaction objekt.
Objekt CommittableTransaction nelze znovu použít. CommittableTransaction Jakmile je objekt potvrzen nebo vrácen zpět, nelze jej znovu použít v transakci. To znamená, že to nelze nastavit jako aktuální kontext transakce.
Vytvoření potvrditelné transakce
Následující ukázka vytvoří nový CommittableTransaction a potvrdí jej.
//Create a committable transaction
tx = new CommittableTransaction();
SqlConnection myConnection = new SqlConnection("server=(local)\\SQLExpress;Integrated Security=SSPI;database=northwind");
SqlCommand myCommand = new SqlCommand();
//Open the SQL connection
myConnection.Open();
//Give the transaction to SQL to enlist with
myConnection.EnlistTransaction(tx);
myCommand.Connection = myConnection;
// Restore database to near it's original condition so sample will work correctly.
myCommand.CommandText = "DELETE FROM Region WHERE (RegionID = 100) OR (RegionID = 101)";
myCommand.ExecuteNonQuery();
// Insert the first record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'MidWestern')";
myCommand.ExecuteNonQuery();
// Insert the second record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'MidEastern')";
myCommand.ExecuteNonQuery();
// Commit or rollback the transaction
while (true)
{
Console.Write("Commit or Rollback? [C|R] ");
ConsoleKeyInfo c = Console.ReadKey();
Console.WriteLine();
if ((c.KeyChar == 'C') || (c.KeyChar == 'c'))
{
tx.Commit();
break;
}
else if ((c.KeyChar == 'R') || (c.KeyChar == 'r'))
{
tx.Rollback();
break;
}
}
myConnection.Close();
tx = null;
tx = New CommittableTransaction
Dim myConnection As New SqlConnection("server=(local)\SQLExpress;Integrated Security=SSPI;database=northwind")
Dim myCommand As New SqlCommand()
'Open the SQL connection
myConnection.Open()
'Give the transaction to SQL to enlist with
myConnection.EnlistTransaction(tx)
myCommand.Connection = myConnection
'Restore database to near it's original condition so sample will work correctly.
myCommand.CommandText = "DELETE FROM Region WHERE (RegionID = 100) OR (RegionID = 101)"
myCommand.ExecuteNonQuery()
'Insert the first record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'MidWestern')"
myCommand.ExecuteNonQuery()
'Insert the second record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'MidEastern')"
myCommand.ExecuteNonQuery()
'Commit or rollback the transaction
Dim c As ConsoleKeyInfo
While (True)
Console.Write("Commit or Rollback? [C|R] ")
c = Console.ReadKey()
Console.WriteLine()
If (c.KeyChar = "C") Or (c.KeyChar = "c") Then
tx.Commit()
Exit While
ElseIf ((c.KeyChar = "R") Or (c.KeyChar = "r")) Then
tx.Rollback()
Exit While
End If
End While
myConnection.Close()
tx = Nothing
Vytvoření instance CommittableTransaction nenastavuje automaticky kontext okolí transakce. Proto jakákoli operace ve Správci prostředků není součástí této transakce. Statická Current vlastnost na globálním Transaction objektu se používá k nastavení nebo načtení ambientní transakce a aplikace ji musí nastavit ručně, aby správci zdrojů mohli účastnit transakce. Je také dobré uložit starou ambientní transakci a opětovně ji obnovit, jakmile dokončíte používání objektu CommittableTransaction.
Chcete-li potvrdit transakci, musíte explicitně volat metodu Commit . Pro vrácení transakce byste měli volat metodu Rollback. Je důležité mít na paměti, že dokud CommittableTransaction nebude potvrzen nebo zrušen, všechny prostředky, které jsou součástí této transakce, jsou stále uzamčeny.
Objekt CommittableTransaction lze použít napříč voláními funkcí a vlákny. Vývojář aplikace ale musí zpracovávat výjimky a konkrétně volat metodu Rollback(Exception) v případě selhání.
Asynchronní potvrzení
Třída CommittableTransaction také poskytuje mechanismus pro potvrzení transakce asynchronně. Potvrzení transakce může trvat delší dobu, protože může zahrnovat více přístupů k databázi a možnou latenci sítě. Pokud chcete zabránit zablokování v aplikacích s vysokou propustností, můžete k dokončení transakční práce co nejdříve použít asynchronní potvrzení a spustit operaci potvrzení jako úlohu na pozadí. Metody BeginCommit a EndCommit metody CommittableTransaction třídy vám to umožňují.
Zavolejte BeginCommit pro odeslání zpoždění potvrzení do vlákna z fondu vláken. Můžete také volat EndCommit k určení, zda transakce byla skutečně potvrzena. Pokud se transakci nepodařilo potvrdit z jakéhokoli důvodu, EndCommit vyvolá výjimku transakce. Pokud transakce ještě není potvrzena v době, kdy je EndCommit zavolán, volající bude zablokován, dokud transakce nebude potvrzena nebo přerušena.
Nejjednodušší způsob, jak provést asynchronní potvrzení, je poskytnutím metody zpětného volání, která se má volat při dokončení potvrzení. Musíte však volat metodu EndCommit na původním CommittableTransaction objektu použitém k vyvolání volání. Chcete-li získat tento objekt, můžete parametr metody zpětně volané přetypovat dolů IAsyncResult, protože CommittableTransaction třída implementuje IAsyncResult třídu.
Následující příklad ukazuje, jak provést asynchronní potvrzení.
public void DoTransactionalWork()
{
Transaction oldAmbient = Transaction.Current;
CommittableTransaction committableTransaction = new CommittableTransaction();
Transaction.Current = committableTransaction;
try
{
/* Perform transactional work here */
// No errors - commit transaction asynchronously
committableTransaction.BeginCommit(OnCommitted,null);
}
finally
{
//Restore the ambient transaction
Transaction.Current = oldAmbient;
}
}
void OnCommitted(IAsyncResult asyncResult)
{
CommittableTransaction committableTransaction;
committableTransaction = asyncResult as CommittableTransaction;
Debug.Assert(committableTransaction != null);
try
{
using(committableTransaction)
{
committableTransaction.EndCommit(asyncResult);
}
}
catch(TransactionException e)
{
//Handle the failure to commit
}
}