Compartir a través de


Flujo de la transacción WS

Download sample

Este ejemplo muestra el uso de una transacción coordinada por cliente y las opciones de servidor y cliente para el flujo de la transacción utilizando la Transacción atómica del WS o el protocolo OleTransactions. Este ejemplo está basado en Ejemplo de introducción que implementa un servicio de calculadora, pero las operaciones se atribuyen para mostrar el uso de TransactionFlowAttribute con la enumeración TransactionFlowOption para determinar para qué flujo de transacción de grado está habilitado. Dentro del ámbito de la transacción fluida, un registro de las operaciones solicitadas se escribe a una base de datos y se conserva hasta que la transacción coordinada por el cliente se ha completado - si la transacción del cliente no se completa, la transacción del Servicio Web se asegura de que no se confirmen las actualizaciones adecuadas a la base de datos.

Nota

Las instrucciones de compilación y el procedimiento de instalación de este ejemplo se encuentran al final de este tema.

Después de iniciar una conexión al servicio y una transacción, el cliente tiene acceso a varias operaciones del servicio. El contrato para el servicio se define como sigue con cada una de las operaciones que muestran un valor diferente para TransactionFlowOption:

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    double Add(double n1, double n2);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Allowed)]
    double Subtract(double n1, double n2);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.NotAllowed)]
    double Multiply(double n1, double n2);
    [OperationContract]
    double Divide(double n1, double n2); 
}

Esto define las operaciones en el orden que serán procesadas:

  • Una solicitud de operación Sumar debe incluir una transacción fluida.

  • Una solicitud de la operación Restar puede incluir una transacción fluida.

  • Una solicitud de operación Multiplicar no debe incluir una transacción fluida a través del valor NotAllowed explícito.

  • Una solicitud de operación Dividir no debe incluir una transacción fluida a través de la omisión de un atributo TransactionFlow.

Para habilitar el flujo de la transacción, los enlaces con la propiedad habilitada transactionFlow se deben utilizar además de los atributos de operación adecuados. En este ejemplo, la configuración del servicio expone un extremo del TCP y un extremo HTTP además del extremo de intercambio de metadatos. El extremo del TCP y el extremo HTTP utilizan los enlaces siguientes, los cuales tiene habilitada la propiedad transactionFlow:

<bindings>
  <netTcpBinding>
    <binding name="transactionalOleTransactionsTcpBinding"
             transactionFlow="true"
             transactionProtocol="OleTransactions"/>
  </netTcpBinding>
  <wsHttpBinding>
    <binding name="transactionalWsatHttpBinding"
             transactionFlow="true" />
  </wsHttpBinding>
</bindings>

Nota

El netTcpBinding proporcionado por el sistema permite especificaciones de transactionProtocol, mientras que el wsHttpBinding proporcionado por el sistema utiliza solamente el protocolo más interoperable WSAtomicTransactionOctober2004. El protocolo OleTransactions sólo está disponible para su uso por clientes Windows Communication Foundation (WCF).

Para la clase que implementa la interfaz ICalculator, todos los métodos se atribuyen con propiedad TransactionScopeRequired establecida en true. Este valor declara que todas las acciones tomadas dentro del método se producen dentro del ámbito de una transacción. En este caso, las acciones tomadas incluyen la grabación a la base de datos de registro. Si la solicitud de la operación incluye a continuación una transacción fluida las acciones se producen dentro del ámbito de la transacción entrante o se genera automáticamente un nuevo ámbito de la transacción.

Nota

La propiedad TransactionScopeRequired define el comportamiento local de las implementaciones de método de servicio y no define la capacidad del cliente ni el requisito para que una transacción fluya.

// Service class which implements the service contract.
[ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable)]
public class CalculatorService : ICalculator
{
    [OperationBehavior(TransactionScopeRequired = true)]
    public double Add(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Adding {0} to {1}", n1, n2));
        return n1 + n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Subtract(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Subtracting {0} from {1}", n2, n1));
        return n1 - n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Multiply(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Multiplying {0} by {1}", n1, n2));
        return n1 * n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Divide(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Dividing {0} by {1}", n1, n2));
        return n1 / n2;
    }

    // Logging method omitted for brevity
}

En el cliente, la configuración de TransactionFlowOption del servicio en las operaciones se refleja en la definición generada del cliente de la interfaz ICalculator. Asimismo, los valores de propiedades del servicio TransactionFlow se reflejan en la configuración de la aplicación del cliente. El cliente puede seleccionar el transporte y el protocolo seleccionando el endpointConfigurationName adecuado:

// Create a client using either wsat or oletx endpoint configurations
CalculatorClient client = new CalculatorClient("WSAtomicTransaction_endpoint");
// CalculatorClient client = new CalculatorClient("OleTransactions_endpoint");

Nota

El comportamiento observado de este ejemplo es el mismo , independientemente de qué protocolo o transporte se elige.

Habiendo iniciado la conexión al servicio, el cliente crea un nuevo TransactionScope alrededor de las llamadas a las operaciones del servicio:

// Start a transaction scope
using (TransactionScope tx =
            new TransactionScope(TransactionScopeOption.RequiresNew))
{
    Console.WriteLine("Starting transaction");

    // Call the Add service operation
    //  - generatedClient will flow the required active transaction
    double value1 = 100.00D;
    double value2 = 15.99D;
    double result = client.Add(value1, value2);
    Console.WriteLine("  Add({0},{1}) = {2}", value1, value2, result);

    // Call the Subtract service operation
    //  - generatedClient will flow the allowed active transaction
    value1 = 145.00D;
    value2 = 76.54D;
    result = client.Subtract(value1, value2);
    Console.WriteLine("  Subtract({0},{1}) = {2}", value1, value2, result);

    // Start a transaction scope that suppresses the current transaction
    using (TransactionScope txSuppress =
                new TransactionScope(TransactionScopeOption.Suppress))
    {
        // Call the Subtract service operation
        //  - the active transaction is suppressed from the generatedClient
        //    and no transaction will flow
        value1 = 21.05D;
        value2 = 42.16D;
        result = client.Subtract(value1, value2);
        Console.WriteLine("  Subtract({0},{1}) = {2}", value1, value2, result);

        // Complete the suppressed scope
        txSuppress.Complete();
    }

    // Call the Multiply service operation
    // - generatedClient will not flow the active transaction
    value1 = 9.00D;
    value2 = 81.25D;
    result = client.Multiply(value1, value2);
    Console.WriteLine("  Multiply({0},{1}) = {2}", value1, value2, result);

    // Call the Divide service operation.
    // - generatedClient will not flow the active transaction
    value1 = 22.00D;
    value2 = 7.00D;
    result = client.Divide(value1, value2);
    Console.WriteLine("  Divide({0},{1}) = {2}", value1, value2, result);

    // Complete the transaction scope
    Console.WriteLine("  Completing transaction");
    tx.Complete();
}

Console.WriteLine("Transaction committed");

Las llamadas a las operaciones son como sigue:

  • La solicitud Sumar provoca que la transacción necesaria fluya hasta al servicio y las acciones del servicio se producen dentro del ámbito de la transacción del cliente.

  • La primera solicitud de Resta también fluye la transacción permitida hacia el servicio y de nuevo las acciones del servicio se producen dentro del ámbito de la transacción del cliente.

  • La solicitud de Restar se realiza dentro de un nuevo ámbito de la transacción declarado con la opción TransactionScopeOption.Suppress. Esto suprime la transacción exterior inicial del cliente y la solicitud no fluye hasta una transacción al servicio. Este enfoque permite a un cliente cancelar explícitamente una suscripción y protegerse contra el fluir de una transacción a un servicio cuando no es necesario. Las acciones del servicio se producen dentro del ámbito de una transacción nueva y no conectada.

  • La solicitud de Multiplicar no fluye una transacción al servicio porque la definición generada del cliente de la interfaz ICalculator incluye un conjunto TransactionFlowAttribute establecida enTransactionFlowOptionNotAllowed.

  • La solicitud de Dividir no fluye una transacción al servicio porque, de nuevo, la definición de la interfaz ICalculator generada del cliente, no incluye un TransactionFlowAttribute. Las acciones del servicio se producen de nuevo dentro del ámbito de otra transacción nueva y no conectada.

Al ejecutar el ejemplo, las solicitudes y respuestas de la operación se muestran en la ventana de la consola del cliente. Presione ENTRAR en la ventana de cliente para cerrar el cliente.

Starting transaction
  Add(100,15.99) = 115.99
  Subtract(145,76.54) = 68.46
  Subtract(21.05,42.16) = -21.11
  Multiply(9,81.25) = 731.25
  Divide(22,7) = 3.14285714285714
  Completing transaction
Transaction committed
Press <ENTER> to terminate client.

El registro de las solicitudes de operación de servicio se muestra en la ventana de la consola del servicio. Presione Entrar en la ventana de cliente para cerrar el cliente.

Press <ENTER> to terminate the service.
  Writing row to database: Adding 100 to 15.99
  Writing row to database: Subtracting 76.54 from 145
  Writing row to database: Subtracting 42.16 from 21.05
  Writing row to database: Multiplying 9 by 81.25
  Writing row to database: Dividing 22 by 7

Después de una ejecución correcta, el ámbito de la transacción del cliente se completa y se confirman todas las acciones tomadas dentro de ese ámbito. Específicamente, los 5 registros nombrados se conservan en la base de datos del servicio. Los 2 primeros de éstos se han producido dentro del ámbito de la transacción del cliente.

Si se produce una excepción en cualquier parte a continuación dentro del TransactionScope del cliente la transacción no puede completarse. Esto produce que los registros registrados dentro de ese ámbito no se confirmen en la base de datos. Este efecto se puede observar repitiendo el ejemplo ejecutado después de marcar como comentario la llamada para completar el TransactionScope exterior. Sólo en este tipo de carrera, las últimas 3 acciones (de la segunda solicitud de restar, la de Multiplicar y la de Dividir) están registradas porque la transacción del cliente no fluyó hacia aquéllos.

Para configurar, generar y ejecutar el ejemplo

  1. Asegúrese de que ha instalado SQL Server 2005 Express Edition o SQL Server 2005. En el archivo App.config del servicio, puede establecerse la base de datos connectionString o pueden deshabilitarse las interacciones de la base de datos estableciendo el valor appSettings usingSql en false.

  2. Para generar el código C# o Visual Basic .NET Edition de la solución, siga las instrucciones de Generación de ejemplos de Windows Communication Foundation.

  3. Utilice la herramienta WsatConfig.exe en Windows SDK para habilitar la compatibilidad para red de Transacciones WCF.

  4. Para ejecutar el ejemplo en una configuración de equipos única o cruzada, siga las instrucciones de Ejecución de ejemplos de Windows Communication Foundation.

Si se ejecuta el ejemplo en los equipos, debe configurarse el Microsoft DTC (MSDTC, Coordinador de transacciones distribuidas), para habilitar el flujo de transacción de red y utilizar la herramienta WsatConfig.exe para habilitar la compatibilidad de red de las transacciones de WCF.

Para configurar Microsoft DTC (MSDTC, Coordinador de transacciones distribuidas) para permitir la ejecución del ejemplo en los equipos

  1. En el equipo de servicio, configure MSDTC para permitir las transacciones de red entrantes.

    1. En el menú Inicio, desplácese a Panel de control, después a Herramientas administrativas y por último a Servicios de componentes.

    2. Haga clic con el botón secundario en Mi PC y seleccione Propiedades.

    3. En la ficha MSDTC, haga clic en Configuración de seguridad.

    4. Marque Acceso a DTC desde la red y Permitir entrantes.

    5. Haga clic en para reiniciar el servicio MSDTC y a continuación, haga clic en Aceptar.

    6. Haga clic en Aceptar para cerrar el cuadro de diálogo.

  2. En el equipo de servicio y el equipo cliente, configure el Firewall de Windows para incluir Microsoft DTC (MSDTC, Coordinador de transacciones distribuidas) en la lista de aplicaciones exceptuadas:

    1. Ejecute la aplicación Firewall de Windows desde el Panel de control.

    2. En la ficha Excepciones, haga clic en Agregar programa.

    3. Desplácese a la carpeta C:\WINDOWS\System32.

    4. Seleccione Msdtc.exe y haga clic en Abrir.

    5. Haga clic en Aceptar para cerrar el cuadro de diálogo Agregar programa y haga clic de nuevo en Aceptar para cerrar el applet Firewall de Windows.

  3. En el equipo cliente, configure MSDTC para permitir las transacciones de red salientes:

    1. En el menú Inicio, desplácese hasta el Panel de control, después vaya a Herramientas administrativas y, por último, a Servicios de componentes.

    2. Haga clic con el botón secundario en Mi PC y seleccione Propiedades.

    3. En la ficha MSDTC, haga clic en Configuración de seguridad.

    4. Marque Acceso a DTC desde la red y Permitir salientes.

    5. Haga clic en para reiniciar el servicio de MS DTC y después haga clic en Aceptar.

    6. Haga clic en Aceptar para cerrar el cuadro de diálogo.

Footer image

Copyright © 2007 Microsoft Corporation. Reservados todos los derechos.