Compartir a través de


Enlistar recursos como participantes en una transacción

Cada recurso que participa en una transacción se administra mediante un administrador de recursos, cuyas acciones están coordinadas por un administrador de transacciones. La coordinación se realiza a través de notificaciones dadas a los suscriptores que se han inscrito en una transacción a través del administrador de transacciones.

En este tema se explica cómo se puede inscribir un recurso (o varios recursos) en una transacción, así como los distintos tipos de inscripción. En el tema Confirmar una transacción en fase única y múltiple se explica cómo se puede coordinar el compromiso de transacción entre los recursos inscritos.

Inscribir recursos en una transacción

Para que un recurso participe en una transacción, debe inscribirse en la transacción. La Transaction clase define un conjunto de métodos cuyos nombres comienzan por Enlist que proporcionan esta funcionalidad. Los distintos métodos Enlist corresponden a los distintos tipos de inscripción que puede tener un administrador de recursos. En concreto, se usan los métodos para los EnlistVolatile recursos volátiles y el EnlistDurable método para los recursos duraderos. La durabilidad (o, por el contrario, la volatilidad) de un administrador de recursos hace referencia a si el administrador de recursos admite la recuperación de errores. Si un administrador de recursos admite la recuperación de errores, conserva los datos en un almacenamiento duradero durante la fase1 (preparación) de modo que, si el administrador de recursos deja de funcionar, puede volver a inscribirse en la transacción tras la recuperación y realizar las acciones adecuadas en función de las notificaciones recibidas de TM. En general, los administradores de recursos volátiles administran recursos volátiles, como una estructura de datos en memoria (por ejemplo, una tabla hash transaccionada en memoria) y los administradores de recursos duraderos administran recursos que tienen un almacén de respaldo más persistente (por ejemplo, una base de datos cuyo almacén de respaldo es disco).

Para simplificar, después de decidir si utilizar el métodoEnlistDurable o EnlistVolatile basado en la compatibilidad de la duración de su recurso, debería dar de alta su recurso para participar en la confirmación en dos fases (2PC) implementando la interfaz IEnlistmentNotification para su administrador de recursos. Para obtener más información sobre 2PC, consulte Confirmar una transacción en fase única y múltiple.

Un solo participante puede inscribirse para más de uno de estos protocolos llamando a EnlistDurable y EnlistVolatile varias veces.

Inscripción duradera

Los EnlistDurable métodos se usan para alistar a un administrador de recursos para participar en la transacción como un recurso duradero. Se espera que si un administrador de recursos duradero se derrumba en el medio de una transacción, puede realizar la recuperación una vez devuelta la línea volviendo a darle de alta (utilizando el método Reenlist) en todas las transacciones en las que fue un participante y no completó la fase 2, y RecoveryComplete de la llamada cuando finaliza el procesamiento de la recuperación. Para obtener más información sobre la recuperación, vea Realizar recuperación.

Todos EnlistDurable los métodos toman un Guid objeto como primer parámetro. Guid El administrador de transacciones lo usa para asociar una inscripción duradera a un administrador de recursos determinado. Por lo tanto, es imperativo que un administrador de recursos use de forma coherente lo mismo Guid para identificarse incluso en distintos administradores de recursos al reiniciarse; de lo contrario, se puede producir un error en la recuperación.

El segundo parámetro del EnlistDurable método es una referencia al objeto que implementa el administrador de recursos para recibir notificaciones de transacción. La sobrecarga que utiliza informa al administrador de transacciones si su administrador de recursos admite la optimización de la fase de confirmación única(SPC). La mayoría de las veces, implementaría la interfaz IEnlistmentNotification para tomar la parte en la confirmación en dos fases (2PC). Sin embargo, si desea optimizar el proceso de confirmación, puede considerar la posibilidad de implementar la ISinglePhaseNotification interfaz para SPC. Para obtener más información sobre SPC, vea Confirmar una transacción en fase única y múltiple y optimización mediante confirmación de fase única y notificación de fase única promocionable.

El tercer parámetro es una EnlistmentOptions enumeración, cuyo valor puede ser None o EnlistDuringPrepareRequired. Si el valor está establecido en EnlistDuringPrepareRequired, la inscripción puede dar de alta los administradores de recursos adicionales al recibir la notificación de preparación del administrador de transacciones. Sin embargo, debe tener en cuenta que este tipo de alistamiento no es elegible para la optimización de compromiso de fase única.

Inscripción volátil

Los participantes que administran recursos volátiles, como una memoria caché, deben inscribirse mediante los EnlistVolatile métodos . Es posible que estos objetos no puedan obtener el resultado de una transacción o recuperar el estado de cualquier transacción en la que participan después de un error del sistema.

Como se indicó anteriormente, un administrador de recursos haría una inscripción volátil si administra un recurso volátil en memoria. Una de las ventajas de usar EnlistVolatile es que no fuerza una extensión innecesaria de la transacción. Para obtener más información sobre la escalación de transacciones, consulte el tema Escalado de administración de transacciones . La volatilidad de la inscripción implica una diferencia en la forma en que el administrador de transacciones controla la inscripción, así como lo que se espera del administrador de recursos por parte del administrador de transacciones. Esto se debe a que un administrador de recursos volátil no realiza la recuperación. Los métodos EnlistVolatile no toman un parámetro Guid, porque un administrador de recursos volátil no realiza la recuperación y no llama al método Reenlist que necesita Guid.

Como con inscripciones duraderas, el método de sobrecarga que se utiliza para dar de alta indica al administrador de transacciones si su administrador de recursos admite la optimización de la fase de confirmación única. Dado que un administrador de recursos volátil no puede realizar la recuperación, no se escribe información de recuperación para una inscripción volátil durante la fase de preparación. Por lo tanto, llamar al RecoveryInformation método da como resultado un InvalidOperationException.

En el ejemplo siguiente se muestra cómo inscribir este objeto como participante en una transacción mediante el EnlistVolatile método .

static void Main(string[] args)
{
    try
    {
        using (TransactionScope scope = new TransactionScope())
        {

            //Create an enlistment object
            myEnlistmentClass myEnlistment = new myEnlistmentClass();

            //Enlist on the current transaction with the enlistment object
            Transaction.Current.EnlistVolatile(myEnlistment, 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 in doubt notification is received

        //Declare done on the enlistment
        enlistment.Done();
    }
}
    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 in doubt notification is received

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

Optimización del rendimiento

La clase Transaction también proporciona el método EnlistPromotableSinglePhase para dar de alta una Inscripción de fase única promocional (PSPE). Esto permite que un administrador de recursos duradero (RM) hospede y "posee" una transacción que posteriormente se pueda escalar para que la MSDTC lo administre si es necesario. Para obtener más información, vea Optimización mediante el uso de la confirmación de fase única y de la inscripción de fase única promovible.

Consulte también