Compartir a través de


Flujo de transacciones dentro y fuera de los servicios de flujo de trabajo

Los servicios de flujo de trabajo y los clientes pueden participar en transacciones. Para que una operación de servicio forme parte de una transacción ambiental, coloque una Receive actividad dentro de una TransactedReceiveScope actividad. En cualquier llamada realizada por un objeto Send o una actividad de SendReply dentro de TransactedReceiveScope también se realizará dentro de la transacción de ambiente. Una aplicación cliente del flujo de trabajo puede crear una transacción de ambiente utilizando la actividad de TransactionScope y operaciones de servicio de llamada que usen la transacción de ambiente. Este tema le guía a través de la creación de un servicio de flujo de trabajo y un cliente de flujo de trabajo que participan en transacciones.

Advertencia

Si una instancia de servicio de flujo de trabajo se carga dentro de una transacción y el flujo de trabajo contiene una Persist actividad, la instancia de flujo de trabajo se bloqueará hasta que se agote el tiempo de espera de la transacción.

Importante

Siempre que use un objeto TransactedReceiveScope se recomienda que coloque todas las recepciones en el flujo de trabajo dentro de actividades TransactedReceiveScope.

Importante

Al usar TransactedReceiveScope y los mensajes llegan en el orden incorrecto, el flujo de trabajo se anulará al intentar entregar el primer mensaje desordenado. Debe asegurarse de que el flujo de trabajo siempre está en un punto de detención coherente cuando el flujo de trabajo está inactivo. Esto le permitirá reiniciar el flujo de trabajo desde un punto de persistencia anterior si se anula el flujo de trabajo.

Creación de una biblioteca compartida

  1. Cree una nueva solución vacía de Visual Studio.

  2. Agregue un nuevo proyecto de biblioteca de clases denominado Common. Agregue referencias a los ensamblados siguientes:

    • System.Activities.dll

    • System.ServiceModel.dll

    • System.ServiceModel.Activities.dll

    • System.Transactions.dll

  3. Agregue una nueva clase llamada PrintTransactionInfo al Common proyecto. Esta clase se deriva de NativeActivity y sobrecarga el Execute método .

    using System;  
    using System;  
    using System.Activities;  
    using System.Transactions;  
    
    namespace Common  
    {  
        public class PrintTransactionInfo : NativeActivity  
        {  
            protected override void Execute(NativeActivityContext context)  
            {  
                RuntimeTransactionHandle rth = context.Properties.Find(typeof(RuntimeTransactionHandle).FullName) as RuntimeTransactionHandle;  
    
                if (rth == null)  
                {  
                    Console.WriteLine("There is no ambient RuntimeTransactionHandle");  
                }  
    
                Transaction t = rth.GetCurrentTransaction(context);  
    
                if (t == null)  
                {  
                    Console.WriteLine("There is no ambient transaction");  
                }  
                else  
                {  
                    Console.WriteLine("Transaction: {0} is {1}", t.TransactionInformation.DistributedIdentifier, t.TransactionInformation.Status);  
                }  
            }  
        }  
    
    }  
    

    Se trata de una actividad nativa que muestra información sobre la transacción ambiental y se usa en los flujos de trabajo de servicio y cliente usados en este tema. Compile la solución para que esta actividad esté disponible en la sección Común del Cuadro de herramientas.

Implementación del servicio de flujo de trabajo

  1. Agregue un nuevo servicio de flujo de trabajo WCF, llamado WorkflowService al proyecto Common. Para ello, haga clic con el botón derecho en el Common proyecto, seleccione Agregar, Nuevo elemento ..., Seleccione Flujo de trabajo en Plantillas instaladas y seleccione Servicio de flujo de trabajo de WCF.

    Agregar un servicio de flujo de trabajo

  2. Elimine las actividades predeterminadas ReceiveRequest y SendResponse.

  3. Arrastre y coloque una actividad de WriteLine en la actividad de Sequential Service. Establezca la propiedad de texto en "Workflow Service starting ...", como se muestra en el ejemplo siguiente.

    ![Incorporación de una actividad WriteLine a la actividad de servicio secuencial(./media/flow-transactions-into-and-out-of-workflow-services/add-writeline-sequential-service.jpg)

  4. Arrastre y coloque una actividad TransactedReceiveScope después de la actividad de WriteLine. La TransactedReceiveScope actividad se puede encontrar en la sección Mensajería del Cuadro de herramientas. La TransactedReceiveScope actividad se compone de dos secciones Request y Body. La sección Solicitud contiene la Receive actividad. La sección Cuerpo contiene las actividades que se van a ejecutar dentro de una transacción después de recibir un mensaje.

    Añadir la actividad TransactedReceiveScope

  5. Seleccione la TransactedReceiveScope actividad y haga clic en el botón Variables . Agregue las variables siguientes.

    Adición de variables a TransactedReceiveScope

    Nota:

    Puede eliminar la variable de datos que está allí de forma predeterminada. También puede utilizar la variable de controlador existente.

  6. Arrastre y coloque una actividad Receive dentro de la sección Solicitud de la actividad TransactedReceiveScope. Establezca las siguientes propiedades:

    Propiedad Importancia
    CanCreateInstance Verdadero (marque la casilla)
    NombreDeOperación StartSample
    NombreDelContratoDeServicio ITransactionSample

    El flujo de trabajo debe tener este aspecto:

    Agregar una actividad Receive

  7. Haga clic en el vínculo Definir... de la Receive actividad y haga lo siguiente:

    Establecer la configuración del mensaje para la actividad Receive

  8. Arrastre y coloque una actividad de Sequence en la sección Cuerpo de TransactedReceiveScope. Dentro de la actividad de Sequence, arrastre las dos actividades de WriteLine y establezca las propiedades Text como se muestra en la siguiente tabla.

    Actividad Importancia
    Primera propiedad WriteLine "Servicio: recepción completada"
    Segunda propiedad WriteLine "Servicio: recibido = " + requestMessage

    El flujo de trabajo debería tener este aspecto:

    Secuencia después de agregar actividades del tipo WriteLine

  9. Arrastre y coloque la actividad PrintTransactionInfo después de la segunda actividad WriteLine en la sección Cuerpo de la actividad TransactedReceiveScope.

    Secuencia después de agregar PrintTransactionInfo

  10. Arrastre y coloque una Assign actividad después de la PrintTransactionInfo actividad y establezca sus propiedades según la tabla siguiente.

    Propiedad Importancia
    En mensaje de respuesta
    Importancia "Servicio: Envío de respuesta."
  11. Arrastre y coloque una actividad de WriteLine después de la actividad de Assign y establezca su propiedad Text en "Servicio: iniciar respuesta".

    El flujo de trabajo debería tener este aspecto:

    Después de agregar Assign y WriteLine

  12. Haga clic con el botón derecho en la Receive actividad y seleccione Crear SendReply y péguela después de la última WriteLine actividad. Haga clic en el vínculo Definir... de la SendReplyToReceive actividad y haga lo siguiente.

    Configuración del mensaje de respuesta

  13. Arrastra y suelta una actividad WriteLine después de la actividad SendReplyToReceive y establece su propiedad Text en "Servicio: Respuesta enviada".

  14. Arrastre y coloque una WriteLine actividad en la parte inferior del flujo de trabajo y establezca su Text propiedad en "Servicio: Finaliza el flujo de trabajo, presione ENTRAR para salir".

    El flujo de trabajo de servicio completado debe tener este aspecto:

    Flujo de trabajo de servicio completo

Implementación del cliente de flujo de trabajo

  1. Agregue una nueva aplicación de flujo de trabajo de WCF, denominada WorkflowClient al Common proyecto. Para ello, haga clic con el botón derecho en el Common proyecto, seleccione Agregar, Nuevo elemento ..., Seleccione Flujo de trabajo en Plantillas instaladas y seleccione Actividad.

    Agregar un proyecto de actividad

  2. Arrastre y coloque una actividad Sequence en la superficie de diseño.

  3. Dentro de la actividad Sequence, arrastre y coloque la actividad WriteLine y establezca su propiedad Text a "Client: Workflow starting". El flujo de trabajo debería tener este aspecto:

    Agregar una actividad WriteLine

  4. Arrastre y coloque una actividad de TransactionScope después de la actividad de WriteLine. Seleccione la TransactionScope actividad, haga clic en el botón Variables y agregue las siguientes variables.

    Adición de variables a TransactionScope

  5. Arrastre y coloque una actividad de Sequence en el cuerpo de la actividad de TransactionScope.

  6. Arrastre y coloque una actividad de PrintTransactionInfo dentro de Sequence.

  7. Arrastre y coloque una actividad WriteLine después de la actividad PrintTransactionInfo y establezca su propiedad Text en "Cliente: comenzando envío". El flujo de trabajo debería tener este aspecto:

    Agregar cliente: Iniciar actividades de envío

  8. Arrastre y coloque una Send actividad después de la Assign actividad y establezca las siguientes propiedades:

    Propiedad Importancia
    EndpointConfigurationName workflowServiceEndpoint
    NombreDeOperación StartSample
    NombreDelContratoDeServicio ITransactionSample

    El flujo de trabajo debería tener este aspecto:

    Establecimiento de las propiedades de la actividad Send

  9. Haga clic en el vínculo Definir... y haga lo siguiente:

    Configuración para enviar mensajes de actividad

  10. Haga clic con el botón derecho en la Send actividad y seleccione Crear receiveReply. La ReceiveReply actividad se colocará automáticamente después de la Send actividad.

  11. Haga clic en Definir... vínculo en la actividad ReceiveReplyForSend y realice la siguiente configuración:

    Establecimiento de la configuración del mensaje ReceiveForSend

  12. Arrastre y coloque una actividad de WriteLine entre las actividades de Send y ReceiveReply, y establezca su propiedad Text en "Cliente: envío completado".

  13. Arrastre y coloque una actividad de WriteLine después de la actividad de ReceiveReply y establezca su propiedad Text en "Cliente: respuesta recibida = " + replyMessage

  14. Arrastre y coloque una actividad de PrintTransactionInfo después de la actividad de WriteLine.

  15. Arrastre y coloque una WriteLine actividad al final del flujo de trabajo y establezca su Text propiedad en "Finalizar el flujo de trabajo de cliente". El flujo de trabajo de cliente completado debe ser similar al diagrama siguiente.

    Flujo de trabajo de cliente completado

  16. Compile la solución.

Creación de la aplicación de servicio

  1. Agregue un nuevo proyecto de aplicación de consola llamado Service a la solución. Agregue referencias a los ensamblados siguientes:

    1. System.Activities.dll

    2. System.ServiceModel.dll

    3. System.ServiceModel.Activities.dll

  2. Abra el archivo Program.cs generado y el código siguiente:

          static void Main()  
          {  
              Console.WriteLine("Building the server.");  
              using (WorkflowServiceHost host = new WorkflowServiceHost(new DeclarativeServiceWorkflow(), new Uri("net.tcp://localhost:8000/TransactedReceiveService/Declarative")))  
              {
                  //Start the server  
                  host.Open();  
                  Console.WriteLine("Service started.");  
    
                  Console.WriteLine();  
                  Console.ReadLine();  
                  //Shutdown  
                  host.Close();  
              };
          }  
    
  3. Agregue el siguiente archivo app.config al proyecto.

    <?xml version="1.0" encoding="utf-8" ?>  
    <!-- Copyright © Microsoft Corporation.  All rights reserved. -->  
    <configuration>  
        <system.serviceModel>  
            <bindings>  
                <netTcpBinding>  
                    <binding transactionFlow="true" />  
                </netTcpBinding>  
            </bindings>  
        </system.serviceModel>  
    </configuration>  
    

Creación de la aplicación cliente

  1. Agregue un nuevo proyecto de aplicación de consola llamado Client a la solución. Agregue una referencia a System.Activities.dll.

  2. Abra el archivo program.cs y agregue el código siguiente.

    class Program  
    {  
    
        private static AutoResetEvent syncEvent = new AutoResetEvent(false);  
    
        static void Main(string[] args)  
        {  
            //Build client  
            Console.WriteLine("Building the client.");  
            WorkflowApplication client = new WorkflowApplication(new DeclarativeClientWorkflow());  
            client.Completed = Program.Completed;  
            client.Aborted = Program.Aborted;  
            client.OnUnhandledException = Program.OnUnhandledException;  
            //Wait for service to start  
            Console.WriteLine("Press ENTER once service is started.");  
            Console.ReadLine();  
    
            //Start the client
            Console.WriteLine("Starting the client.");  
            client.Run();  
            syncEvent.WaitOne();  
    
            //Sample complete  
            Console.WriteLine();  
            Console.WriteLine("Client complete. Press ENTER to exit.");  
            Console.ReadLine();  
        }  
    
        private static void Completed(WorkflowApplicationCompletedEventArgs e)  
        {  
            Program.syncEvent.Set();  
        }  
    
        private static void Aborted(WorkflowApplicationAbortedEventArgs e)  
        {  
            Console.WriteLine("Client Aborted: {0}", e.Reason);  
            Program.syncEvent.Set();  
        }  
    
        private static UnhandledExceptionAction OnUnhandledException(WorkflowApplicationUnhandledExceptionEventArgs e)  
        {  
            Console.WriteLine("Client had an unhandled exception: {0}", e.UnhandledException);  
            return UnhandledExceptionAction.Cancel;  
        }  
    }  
    

Consulte también