Partager via


Inscription de ressources comme participants à une transaction [ws_fxtransactions_4]

Les ressources participant à une transaction sont managées par un gestionnaire de ressources, dont les actions sont coordonnées par un gestionnaire de transactions. La coordination s'effectue par envoi de notifications aux abonnés qui se sont inscrits à une transaction via le gestionnaire de transactions.

Cette rubrique explique comment inscrire une ressource (ou plusieurs ressources) à une transaction et traite des différents types d'inscription. La rubrique Validation d'une transaction en une phase unique et en plusieurs phases [ws_fxtransactions_4] traite de la coordination de la validation d'une transaction entre les ressources inscrites.

Inscription de ressources à une transaction

Pour qu'une ressource participe à une transaction, elle doit être inscrite à cette transaction. La classe Transaction définit un jeu de méthodes, dont les noms commencent par Enlist, qui fournit cette fonctionnalité. Les différentes méthodes Enlist correspondent aux différents types d'inscription dont peut disposer un gestionnaire de ressources. En particulier, utilisez les méthodes EnlistVolatile pour les ressources volatiles et la méthode EnlistDurable pour les ressources durables. La durabilité (ou à l'inverse la volatilité) d'un gestionnaire de ressources indique s'il prend en charge la récupération après défaillance. Si un gestionnaire de ressources prend en charge la récupération après défaillance, il conserve les données par stockage durable lors de la Phase1 (préparation). Ainsi, s'il connaît une défaillance, il peut à nouveau s'inscrire à la transaction après récupération et procéder aux actions indiquées par les notifications envoyées par le gestionnaire de transactions. En général, les gestionnaires de ressources volatiles gèrent les ressources volatiles, comme une structure de données en mémoire (par exemple, une table de hachage traitée en mémoire), et les gestionnaires de ressources durables gèrent les ressources qui disposent d'un magasin de stockage plus persistant (par exemple, une base de données ayant un disque comme magasin de stockage).

Pour une question de simplicité, après avoir décidé d'utiliser la méthode EnlistDurable ou la méthode EnlistVolatile, selon la prise en charge de la durabilité de la ressource, inscrivez votre ressource pour participer à la validation en deux phases (2PC) en implémentant l'interface IEnlistmentNotification de votre gestionnaire de ressources. Pour plus d'informations sur le protocole 2PC, consultez Validation d'une transaction en une phase unique et en plusieurs phases [ws_fxtransactions_4].

Un participant peut s'inscrire à plusieurs de ces protocoles en appelant EnlistDurable et EnlistVolatile à plusieurs reprises.

Ee818750.collapse_all(fr-fr,VS.120).gifInscription durable

Les méthodes EnlistDurable permettent d'inscrire un gestionnaire de ressources à une transaction en tant de ressource durable. Si un gestionnaire de ressources durables s'arrête en cours de transaction, il peut procéder à la récupération une fois sa remise en ligne effectuée par réinscription (à l'aide de la méthode Reenlist) à toutes les transactions auxquelles il participait et dont il n'a pas terminé la phase 2, et appeler RecoveryComplete une fois le traitement de récupération terminé. Pour plus d'informations sur la récupération, consultez Exécution de la récupération [ws_fxtransactions_4].

Les méthodes EnlistDurable ont toutes un objet Guid pour premier paramètre. Le gestionnaire de transactions utilise le Guid pour associer une inscription durable à un gestionnaire de ressources particulier. Il est donc impératif qu'un gestionnaire de ressources utilise toujours le même Guid pour son identification après redémarrage, même sur plusieurs gestionnaires de ressources, sous peine de faire échouer la récupération.

Le second paramètre des méthodes EnlistDurable est une référence à l'objet que le gestionnaire de ressources implémente pour recevoir les notifications de transaction. La surcharge que vous utilisez indique au gestionnaire de transactions si votre gestionnaire de ressources prend en charge l'optimisation de validation à phase unique (SPC). Dans la plupart des cas, vous implémenterez l'interface IEnlistmentNotification pour participer à la validation en deux phases (2PC). Cependant, si vous souhaitez optimiser le processus de validation, envisagez d'implémenter l'interface ISinglePhaseNotification pour SPC. Pour plus d'informations sur la SPC, consultez Validation d'une transaction en une phase unique et en plusieurs phases [ws_fxtransactions_4] et Optimisation à l'aide de la validation à phase unique et de la notification de phase unique pouvant être promue [ws_fxtransactions_4].

Le troisième paramètre est une énumération EnlistmentOptions, dont la valeur peut être None ou EnlistDuringPrepareRequired. Si la valeur est EnlistDuringPrepareRequired, l'inscription peut autoriser des gestionnaires de ressources supplémentaires après réception de la notification de préparation envoyée par le gestionnaire de transactions. Toutefois, vous devez savoir que ce type d'inscription n'est pas pris en charge pour l'optimisation de la validation en une phase.

Ee818750.collapse_all(fr-fr,VS.120).gifInscription volatile

Les participants gérant des ressources volatiles telles qu'un cache doivent s'inscrire à l'aide des méthodes EnlistVolatile. Il est possible que ces objets ne puissent pas obtenir le résultat d'une transaction ou récupérer l'état d'une transaction à laquelle ils participent après une défaillance système.

Comme indiqué précédemment, un gestionnaire de ressources procède à une inscription volatile s'il manage une ressource volatile en mémoire. L'un des avantages offert par EnlistVolatile est que cela évite une remontée inutile de la transaction. Pour plus d'informations sur la remontée des transactions, consultez la rubrique Remontée de la gestion des transactions [ws_fxtransactions_4]. Une inscription volatile implique une différence de traitement de l'inscription par le gestionnaire de transactions, ainsi qu'une modification des attentes du gestionnaire de transactions concernant le gestionnaire de ressources. Cela est dû au fait que les gestionnaires de ressources volatiles ne prennent pas en charge la récupération. Les méthodes EnlistVolatile n'ont pas de paramètre Guid car les gestionnaires de ressources volatiles ne prennent pas en charge la récupération et n'appellent donc jamais la méthode Reenlist, qui requiert un Guid.

Comme pour les inscriptions durables, la méthode de surcharge utilisée pour vous inscrire indique au gestionnaire de transactions si votre gestionnaire de ressources prend en charge l'optimisation de la validation en une phase. Les gestionnaires de ressources volatiles ne prenant pas en charge la récupération, aucune information de récupération n'est déclarée pour une inscription volatile lors de la phase de préparation. C'est pourquoi appeler la méthode RecoveryInformation entraîne une InvalidOperationException.

L'exemple suivant indique comment inscrire l'un de ces objets à une transaction à l'aide de la méthode EnlistVolatile.

        Public Shared Sub Main()
            Try
                Using scope As TransactionScope = New TransactionScope()

                    'Create an enlistment object
                    Dim myEnlistmentClass As New EnlistmentClass

                    'Enlist on the current transaction with the enlistment object
                    Transaction.Current.EnlistVolatile(myEnlistmentClass, EnlistmentOptions.None)

                    'Perform transactional work here.

                    'Call complete on the TransactionScope based on console input
                    Dim c As ConsoleKeyInfo
                    While (True)
                        Console.Write("Complete the transaction scope? [Y|N] ")
                        c = Console.ReadKey()
                        Console.WriteLine()
                        If (c.KeyChar = "Y") Or (c.KeyChar = "y") Then
                            scope.Complete()
                            Exit While
                        ElseIf ((c.KeyChar = "N") Or (c.KeyChar = "n")) Then
                            Exit While
                        End If
                    End While
                End Using
            Catch ex As TransactionException
                Console.WriteLine(ex)
            Catch
                Console.WriteLine("Cannot complete transaction")
                Throw
            End Try
        End Sub
    End Class

    Public Class EnlistmentClass
        Implements IEnlistmentNotification

        Public Sub Prepare(ByVal myPreparingEnlistment As PreparingEnlistment) Implements System.Transactions.IEnlistmentNotification.Prepare
            Console.WriteLine("Prepare notification received")

            'Perform transactional work
    
            'If work finished correctly, reply with prepared
            myPreparingEnlistment.Prepared()
        End Sub

        Public Sub Commit(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Commit
            Console.WriteLine("Commit notification received")

            'Do any work necessary when commit notification is received

            'Declare done on the enlistment
            myEnlistment.Done()
        End Sub

        Public Sub Rollback(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Rollback
            Console.WriteLine("Rollback notification received")

            'Do any work necessary when rollback notification is received

            'Declare done on the enlistment
            myEnlistment.Done()
        End Sub

        Public Sub InDoubt(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.InDoubt
            Console.WriteLine("In doubt notification received")

            'Do any work necessary when indout notification is received

            'Declare done on the enlistment
            myEnlistment.Done()
        End Sub
    End Class

        static void Main(string[] args)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                
                    //Create an enlistment object
                    myEnlistmentClass myElistment = new myEnlistmentClass();

                    //Enlist on the current transaction with the enlistment object
                    Transaction.Current.EnlistVolatile(myElistment, EnlistmentOptions.None);

                    //Perform transactional work here.

                    //Call complete on the TransactionScope based on console input
                                    ConsoleKeyInfo c;
                    while(true)
                                    {
                        Console.Write("Complete the transaction scope? [Y|N] ");
                        c = Console.ReadKey();
                        Console.WriteLine();
                
                                            if ((c.KeyChar == 'Y') || (c.KeyChar == 'y'))
                        {
                            scope.Complete();
                            break;
                        }
                        else if ((c.KeyChar == 'N') || (c.KeyChar == 'n'))
                        {
                            break;
                        }
                    }
                }
            }
            catch (System.Transactions.TransactionException ex)
            {
                Console.WriteLine(ex);
            }
            catch
            {
                Console.WriteLine("Cannot complete transaction");
                throw;
            }
        }

        class myEnlistmentClass : IEnlistmentNotification
        {
            public void Prepare(PreparingEnlistment preparingEnlistment)
            {
                Console.WriteLine("Prepare notification received");

                //Perform transactional work

                //If work finished correctly, reply prepared
                preparingEnlistment.Prepared();

                // otherwise, do a ForceRollback
                preparingEnlistment.ForceRollback();
            }

            public void Commit(Enlistment enlistment)
            {
                Console.WriteLine("Commit notification received");

                //Do any work necessary when commit notification is received

                //Declare done on the enlistment
                enlistment.Done();
            }

            public void Rollback(Enlistment enlistment)
            {
                Console.WriteLine("Rollback notification received");

                //Do any work necessary when rollback notification is received

                //Declare done on the enlistment
                enlistment.Done();
            }

            public void InDoubt(Enlistment enlistment)
            {
                Console.WriteLine("In doubt notification received");

                //Do any work necessary when indout notification is received
                
                //Declare done on the enlistment
                enlistment.Done();
            }
        }

Ee818750.collapse_all(fr-fr,VS.120).gifOptimisation des performances

La classe Transaction fournit également la méthode EnlistPromotableSinglePhase permettant de s'inscrire à une PSPE (Promotable Single Phase Enlistment). Cela permet à un gestionnaire de ressources durables d'héberger et de « posséder » une transaction qui peut, si nécessaire, être ensuite remontée pour être managée par le MSDTC. Pour plus d'informations, consultez Optimisation à l'aide de la validation à phase unique et de la notification de phase unique pouvant être promue [ws_fxtransactions_4].

Voir aussi

Concepts

Optimisation à l'aide de la validation à phase unique et de la notification de phase unique pouvant être promue [ws_fxtransactions_4]

Validation d'une transaction en une phase unique et en plusieurs phases [ws_fxtransactions_4]