Dar de alta los recursos como participantes en una transacción

Un administrador de recursos administra cada recurso participante, cuyas acciones coordina un administrador de transacciones. La coordinación se hace a través de las notificaciones dadas a los suscriptores que han dado de alta una transacción a través del administrador de transacciones.

En este tema se trata cómo un recurso (o varios recursos) se puede dar de alta en una transacción, así como los tipos diferentes 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.

Dar de alta los recursos en una transacción

Para que un administrador de recursos participe en una transacción, debe inscribirse en la transacción. La clase Transaction define un conjunto de métodos cuyos nombres comienzan con Enlist que proporcionan esta funcionalidad. Los distintos métodos Enlist corresponden a los distintos tipos de inscripción que un administrador de recursos puede tener. Específicamente, utiliza los métodos EnlistVolatile para los recursos volátiles y el método EnlistDurable para los recursos duraderos. La duración (o a la inversa la volatilidad) de un administrador de recursos hace referencia a si el administrador de recursos admite la recuperación del error. Si un administrador de recursos admite la recuperación del error, conserva los datos del almacenamiento duradero durante la fase1 (preparación) de tal manera que si el administrador de recursos baja, puede reenganchar la transacción en la recuperación y realizar las acciones apropiadas basadas en las notificaciones recibidas de la 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 llevada a cabo en memoria) y los administradores de recursos duraderos administran recursos que tienen una memoria auxiliar más persistente (por ejemplo, una base de datos cuyo dispositivo de copia de seguridad es el 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.

Una participante única puede inscribir para más de uno de estos protocolos varias veces llamando a EnlistDurable y a EnlistVolatile.

Inscripción duradera

El método EnlistDurable se utiliza para inscribir un administrador de recursos para la participación 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 recuperación, vea Realización de la recuperación.

Todos métodos EnlistDurable toman un objeto Guid como su primer parámetro. El administrador de transacciones utiliza Guid para asociar una inscripción duradera a un administrador de recursos determinado. Como tal, es imperativo que un administrador de recursos utilice de forma consistente el mismo Guid para incluso identificarse por los administradores de recursos diferentes al reiniciar, de lo contrario se puede producir un error en la recuperación.

El segundo parámetro del método EnlistDurable es una referencia al objeto que el administrador de recursos implementa para recibir las notificaciones de la 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 implementar la interfaz ISinglePhaseNotification 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 enumeración EnlistmentOptions, 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, debería ser consciente de que este tipo de inscripción no es apta para la optimización de la fase de confirmación única.

Inscripción volátil

Los participantes que administran recursos volátiles como una caché, deberían darse de alta utilizando los métodos EnlistVolatile. Tales objetos no podrían obtener el resultado de una transacción o recuperar el estado de cualquier transacción participan después de un error del sistema.

Como dicho previamente, un administrador de recursos realizaría una inscripción volátil si administra un recurso en memoria volátil. Una de las ventajas de utilizar EnlistVolatile es que no fuerza ninguna subida innecesaria de la transacción. Para más información sobre el escalado de transacción, vea el tema Gestión de la elevación de transacciones. El dar de alta volátilmente implica una diferencia entre cómo el administrador de transacciones administra la inscripción, y lo que el administrador de transacciones se espera del administrador de recursos. Esto es porque 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. Puesto que un administrador de recursos volátil no puede realizar la recuperación, ninguna información de la recuperación se escribe para una inscripción volátil durante la fase de preparación. Por consiguiente, llamar al método RecoveryInformation produce InvalidOperationException.

El ejemplo siguiente muestra cómo dar de alta este tipo de objeto como un participante en una transacción utilizando el método EnlistVolatile.

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

Optimizar el 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 a un administrador de recursos duradero (RM) hospedar y "poseer" una transacción que puede realizar una escalada para que sea administrada por MSDTC 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