Creación de un servicio de flujo de trabajo de larga duración
En este artículo se describe cómo crear un servicio de flujo de trabajo de larga duración, que puede ejecutarse durante largos períodos de tiempo. En algún momento, el flujo de trabajo podría quedar inactivo a la espera de recibir alguna información adicional. En este caso, el flujo de trabajo se conserva en una base de datos SQL y se quita de la memoria. Cuando esté disponible la información adicional, la instancia de flujo de trabajo se vuelve a cargar en la memoria y continua ejecutándose.
En este escenario, el usuario implementa un sistema de pedidos muy simplificado. El cliente envía un mensaje inicial al servicio de flujo de trabajo para que inicie el pedido. Devuelve un identificador de pedido al cliente. En este momento el servicio de flujo de trabajo espera otro mensaje del cliente y pasa al estado inactivo, y se conserva en una base de datos SQL Server. Cuando el cliente envía el siguiente mensaje para pedir un elemento, el servicio de flujo de trabajo se vuelve a cargar en memoria y finaliza el procesamiento del pedido.
En el ejemplo de código, devuelve una cadena que indica que el elemento se ha agregado al pedido. No se pretende que el ejemplo de código sea una aplicación real de la tecnología, sino más bien un ejemplo sencillo que ilustre servicios de flujo de trabajo de ejecución prolongada.
Requisitos previos
Debe tener instalado el siguiente software para usar este tutorial:
- Microsoft SQL Server 2008
- Visual Studio 2012
- Microsoft .NET Framework 4.6.1
También debe estar familiarizado con WCF y Visual Studio 2012 y saber crear proyectos o soluciones.
Configuración de SQL Database
Para conservar las instancias del servicio de flujo de trabajo debe tener instalado Microsoft SQL Server y configurar una base de datos con el fin de almacenar las instancias de flujo de trabajo persistentes. Haga clic en el botón Iniciar, seleccione Todos los programas, Microsoft SQL Server 2008 y Microsoft SQL Management Studio para ejecutar Microsoft SQL Management Studio.
Haga clic en el botón Conectar para iniciar sesión en la instancia de SQL Server.
Haga clic con el botón derecho en Bases de datos en la vista de árbol y seleccione Nueva base de datos para crear una nueva base de datos denominada
SQLPersistenceStore
.Ejecute el archivo de script SqlWorkflowInstanceStoreSchema.sql ubicado en el directorio C:\Windows\Microsoft.NET\Framework\v4.0\SQL\es en la base de datos SQLPersistenceStore para configurar los esquemas de base de datos necesarios.
Ejecute el archivo de script SqlWorkflowInstanceStoreLogic.sql ubicado en el directorio C:\Windows\Microsoft.NET\Framework\v4.0\SQL\es en la base de datos SQLPersistenceStore para configurar la lógica de base de datos necesaria.
Creación del servicio de flujo de trabajo hospedado en web
Cree una solución vacía de Visual Studio 2012 y asígnele el nombre
OrderProcessing
.Agregue un nuevo proyecto de aplicación de servicio de flujo de trabajo WCF denominado
OrderService
a la solución.En el cuadro de diálogo de propiedades del proyecto, seleccione la pestaña Web.
Seleccione Página específica en Acción de inicio y especifique
Service1.xamlx
.Seleccione Usar servidor web de IIS local en Servidores.
Advertencia
Debe ejecutar Visual Studio 2012 en modo de administrador para establecer esta configuración.
Estos dos pasos configuran el proyecto de servicio de flujo de trabajo que IIS va a hospedar.
Abra
Service1.xamlx
si aún no está abierto y elimine las actividades ReceiveRequest y SendResponse existentes.Seleccione la actividad Servicio secuencial, haga clic en el vínculo Variables y agregue las variables que se muestran en la siguiente ilustración. De esta forma, se agregan algunas variables que se usarán posteriormente en el servicio de flujo de trabajo.
Nota
Si CorrelationHandle no está en la lista desplegable Tipo de variable, seleccione Buscar tipos en la lista desplegable. Escriba CorrelationHandle en el cuadro Nombre de tipo, seleccione CorrelationHandle en el cuadro de lista y haga clic en Aceptar.
Arrastre y coloque una plantilla de la actividad ReceiveAndSendReply en la actividad Servicio secuencial. Este conjunto de actividades recibirá un mensaje de un cliente y devolverá un respuesta.
Seleccione la actividad Receive y establezca las propiedades resaltadas en la siguiente ilustración.
La propiedad DisplayName establece el nombre mostrado para la actividad Receive en el diseñador. Las propiedades ServiceContractName y OperationName especifican el nombre del contrato de servicio y la operación que implementa la actividad Receive. Para obtener más información sobre cómo se usan los contratos en los servicios de flujo de trabajo, vea Uso de contratos en flujo de trabajo.
Haga clic en el vínculo Definir de la actividad ReceiveStartOrder y establezca las propiedades que se muestran en la siguiente ilustración. Observe que el botón de radio Parámetros está seleccionado y que un parámetro denominado
p_customerName
está enlazado a la variablecustomerName
. De esta forma, se configura la actividad Receive para recibir algunos datos y enlazarlos a variables locales.Seleccione la actividad SendReplyToReceive y establezca la propiedad resaltada que se muestra en la siguiente ilustración.
Haga clic en el vínculo Definir de la actividad SendReplyToStartOrder y establezca las propiedades que se muestran en la siguiente ilustración. Observe que el botón de radio Parámetros está seleccionado y que un parámetro denominado
p_orderId
está enlazado a la variableorderId
. Esta configuración especifica que la actividad SendReplyToStartOrder ejecutará un valor de tipo de cadena en el autor de la llamada.Arrastre y coloque una actividad Assign entre las actividades Receive y SendReply, y establezca las propiedades que se muestran en la siguiente ilustración:
De esta forma, se crea un identificador de nuevo pedido y se coloca el valor en la variable orderId.
Seleccione la actividad ReplyToStartOrder. En la ventana Propiedades, haga clic en el botón de puntos suspensivos de CorrelationInitializers. Seleccione el vínculo Agregar inicializador, escriba
orderIdHandle
en el cuadro de texto Inicializador, seleccione el inicializador de correlación de consultas para el tipo de correlación y p_orderId en el cuadro desplegable Consultas XPATH. Esta configuración se muestra en la siguiente ilustración. Haga clic en OK. De esta forma, se inicializa una correlación entre el cliente y esta instancia del servicio de flujo de trabajo. Cuando se reciba un mensaje con este identificador de pedido, se enruta a esta instancia del servicio de flujo de trabajo.
Arrastre y coloque otra actividad ReceiveAndSendReply al final del flujo de trabajo (fuera de la Secuencia que contiene las primeras actividades Receive y SendReply). De esta forma, se recibirá el segundo mensaje enviado por el cliente y se responderá al mismo.
Seleccione la Secuencia que contenga las actividades Receive y SendReply que se acaban de crear y haga clic en el botón Variables. Agregue la variable resaltada en la siguiente ilustración:
Agregue también
orderResult
como Cadena en el ámbitoSequence
.Seleccione la actividad Receive y establezca las propiedades que se muestran en la siguiente ilustración:
Nota
No olvide cambiar el campo ServiceContractName por
../IAddItem
.Haga clic en el vínculo Definir de la actividad ReceiveAddItem y agregue los parámetros mostrados en la siguiente ilustración. De esta forma, se configura la actividad de recepción para aceptar dos parámetros: el id. de pedido y el id. del elemento que se pide.
Haga clic en el botón de puntos suspensivos de CorrelateOn y escriba
orderIdHandle
. En Consultas XPath, haga clic en la flecha desplegable y seleccionep_orderId
. De esta forma, se configura la correlación de la segunda actividad de recepción. Para obtener más información acerca de la correlación, vea Correlación.Arrastre y coloque una actividad If inmediatamente detrás de la actividad ReceiveAddItem. Esta actividad actúa como instrucción If.
Establezca la propiedad Condition en
itemId=="Zune HD" (itemId="Zune HD" for Visual Basic)
.Arrastre y coloque una actividad Assign en la sección Then y otra en la sección Else. Establezca las propiedades de las actividades Assign, tal como se muestra en la siguiente ilustración.
Si el valor de la condición es
true
, se ejecutará la sección Then. Si el valor de la condición esfalse
, se ejecuta la sección Else.Seleccione la actividad SendReplyToReceive y establezca la propiedad DisplayName que se muestra en la siguiente ilustración.
Haga clic en el vínculo Definir de la actividad SetReplyToAddItem y configúrelo tal como se muestra en la siguiente ilustración. De esta forma, se configura la actividad SendReplyToAddItem para devolver el valor de la variable
orderResult
.
Abra el archivo web.config y agregue los elementos siguientes en la sección <behavior> para habilitar la persistencia del flujo de trabajo. (Asegúrese de que completa la cadena de conexión).
<sqlWorkflowInstanceStore connectionString="...;Asynchronous Processing=True" instanceEncodingOption="None" instanceCompletionAction="DeleteAll" instanceLockedExceptionAction="BasicRetry" hostLockRenewalPeriod="00:00:30" runnableInstancesDetectionPeriod="00:00:02" /> <workflowIdle timeToUnload="0"/>
Compile la solución.
Creación de una aplicación cliente para llamar al servicio de flujo de trabajo
Agregue un nuevo proyecto de aplicación de consola denominado
OrderClient
a la solución.Agregue referencias a los siguientes ensamblados al proyecto
OrderClient
System.ServiceModel.dll
System.ServiceModel.Activities.dll
Agregue una referencia de servicio al servicio de flujo de trabajo y especifique
OrderService
como el espacio de nombres.En el método
Main()
del proyecto de cliente, agregue el siguiente código:static void Main(string[] args) { // Send initial message to start the workflow service Console.WriteLine("Sending start message"); StartOrderClient startProxy = new StartOrderClient(); string orderId = startProxy.StartOrder("Kim Abercrombie"); // The workflow service is now waiting for the second message to be sent Console.WriteLine("Workflow service is idle..."); Console.WriteLine("Press [ENTER] to send an add item message to reactivate the workflow service..."); Console.ReadLine(); // Send the second message Console.WriteLine("Sending add item message"); AddItemClient addProxy = new AddItemClient(); AddItem item = new AddItem(); item.p_itemId = "Zune HD"; item.p_orderId = orderId; string orderResult = addProxy.AddItem(item); Console.WriteLine("Service returned: " + orderResult); }
Compile la solución y ejecute la aplicación
OrderClient
. El cliente mostrará un texto similar al siguiente:Sending start messageWorkflow service is idle...Press [ENTER] to send an add item message to reactivate the workflow service...
Para comprobar que se ha conservado el servicio de flujo de trabajo, inicie SQL Server Management Studio. Para ello, vaya al menú Inicio y seleccione Todos los programas, Microsoft SQL Server 2008, SQL Server Management Studio.
- En el panel de la izquierda expanda Bases de datos, SQLPersistenceStore, Vistas, haga clic con el botón derecho en System.Activities.DurableInstancing.Instances y seleccione Seleccionar las primeras 1000 filas. En el panel Resultados compruebe que ve una instancia como mínimo. Puede que haya otras instancia de ejecuciones previas si se produjo una excepción durante la ejecución. Puede eliminar filas existentes si hace clic con el botón derecho en System.Activities.DurableInstancing.Instances, selecciona Editar las primeras 200 filas, presiona el botón Ejecutar, selecciona todas las filas del panel de resultados y luego Eliminar. Para comprobar que la instancia que se muestra en la base de datos es la instancia de la aplicación creada, compruebe que la vista de instancias esté vacía antes de ejecutar el cliente. Una vez que se ejecute el cliente, vuelva a ejecutar la consulta (Seleccionar las primeras 1000 filas) y compruebe que se haya agregado una nueva instancia.
Presione Entrar para enviar y agregar un mensaje de elemento al servicio de flujo de trabajo. El cliente mostrará un texto similar al siguiente:
Sending add item messageService returned: Item added to orderPress any key to continue . . .