Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
La CommittableTransaction classe fournit un moyen explicite pour les applications d’utiliser une transaction, par opposition à l’utilisation implicite de la TransactionScope classe. Il est utile pour les applications qui souhaitent utiliser la même transaction entre plusieurs appels de fonction ou plusieurs appels de thread. Contrairement à la TransactionScope classe, le développeur de l'application doit appeler spécifiquement les méthodes Commit et Rollback pour valider ou abandonner la transaction.
Vue d’ensemble de la classe CommitableTransaction
La CommittableTransaction classe dérive de la Transaction classe, fournissant donc toutes les fonctionnalités de ce dernier. Plus particulièrement utile est la Rollback méthode sur la Transaction classe qui peut également être utilisée pour restaurer un CommittableTransaction objet.
La Transaction classe est similaire à la CommittableTransaction classe, mais n’offre pas de Commit méthode. Cela vous permet de transmettre l’objet transaction (ou clones de celui-ci) à d’autres méthodes (potentiellement sur d’autres threads) tout en contrôlant quand la transaction est validée. Le code appelé est en mesure d’inscrire et de voter sur la transaction, mais seul le créateur de l’objet CommittableTransaction a la possibilité de valider la transaction.
Vous devez noter les points suivants lors de l’utilisation de la CommittableTransaction classe,
La création d’une CommittableTransaction transaction ne définit pas la transaction ambiante. Vous devez définir et réinitialiser spécifiquement la transaction ambiante pour vous assurer que les gestionnaires de ressources fonctionnent dans le contexte de transaction approprié le cas échéant. La façon de définir la transaction ambiante actuelle consiste à définir la propriété statique Current sur l’objet global Transaction .
Un CommittableTransaction objet ne peut pas être réutilisé. Une fois qu’un CommittableTransaction objet a été validé ou annulé, il ne peut pas être utilisé à nouveau dans une transaction. Autrement dit, il ne peut pas être défini comme contexte de transaction courante.
Création d'une CommittableTransaction
L'exemple suivant illustre la création et la validation d'une nouvelle CommittableTransaction.
//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
La création d’une instance de CommittableTransaction ne définit pas automatiquement le contexte de transaction ambiante. Par conséquent, toute opération sur un gestionnaire de ressources ne fait pas partie de cette transaction. La propriété statique Current sur l’objet global Transaction est utilisée pour définir ou récupérer la transaction ambiante et l’application doit la définir manuellement pour s’assurer que les gestionnaires de ressources peuvent participer à la transaction. Il est également recommandé d’enregistrer l’ancienne transaction ambiante et de la restaurer lorsque vous avez terminé d’utiliser l’objet CommittableTransaction .
Pour valider la transaction, vous devez appeler explicitement la Commit méthode. Pour restaurer une transaction, vous devez appeler la Rollback méthode. Il est important de noter que, jusqu'à la validation ou la restauration d'une CommittableTransaction, toutes les ressources concernées par la transaction sont verrouillées.
Un CommittableTransaction objet peut être utilisé entre les appels de fonction et les threads. Toutefois, il incombe au développeur d’applications de gérer les exceptions et d’appeler spécifiquement la Rollback(Exception) méthode en cas d’échecs.
Validation asynchrone
La CommittableTransaction classe fournit également un mécanisme permettant de valider une transaction de manière asynchrone. Une validation de transaction peut prendre beaucoup de temps, car elle peut impliquer plusieurs accès à la base de données et une latence réseau possible. Lorsque vous souhaitez éviter les blocages dans les applications à débit élevé, vous pouvez utiliser la validation asynchrone pour terminer le travail transactionnel dès que possible et exécuter l’opération de validation en tant que tâche en arrière-plan. Les méthodes BeginCommit et EndCommit de la classe CommittableTransaction vous permettent de le faire.
Vous pouvez appeler BeginCommit pour transmettre la suspension de la validation à un thread du pool de threads. Vous pouvez également appeler EndCommit pour déterminer si la transaction a été validée. Si la transaction n’a pas réussi à valider pour une raison quelconque, EndCommit déclenche une exception de transaction. Si la transaction n’est pas encore validée au moment EndCommit de l’appel, l’appelant est bloqué jusqu’à ce que la transaction soit validée ou abandonnée.
Le moyen le plus simple d’effectuer une validation asynchrone consiste à fournir une méthode de rappel, à appeler lorsque la validation est terminée. Toutefois, vous devez appeler la méthode EndCommit sur l'objet CommittableTransaction d'origine utilisé pour effectuer l'appel. Pour obtenir cet objet, vous pouvez effectuer un transtypage descendant du paramètre IAsyncResult de la méthode de rappel, car la classe CommittableTransaction implémente la classe IAsyncResult.
L’exemple suivant montre comment effectuer une validation asynchrone.
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
}
}