11.02.2011

Aprendiendo WF parte 6: Trabajando con colecciones en WF

Siguiendo con nuestros posts acerca de WF, vamos a trabajar con colecciones en los workflows de Workflow Foundation, algo que también será muy común en nuestras aplicaciones n-layer ya que normalmente trabajamos con colecciones de entidades.

Colecciones como Parámetros

Es muy común utilizar colecciones de objetos para llevar a cabo procesos de negocios en nuestra empresa a través de los productos que día a día desarrollamos. Por ejemplo, vamos a requerir una colección de clientes cuando deseamos hacer una consulta de clientes, o una colección de productos cuando queremos ver los productos de una categoría específica. Como era de suponerse, en el workflow foundation podemos recibir, procesar y retornar colecciones de objetos.

En este post vamos a crear una colección de productos los cuales tienen la siguiente estructura.

image

En el ejemplo que estamos por construir, vamos a recibir una colección de Productos, la vamos a procesar y luego vamos a retornar todos los productos que están exonerados. Para esto vamos a crear un nuevo Workflow que se llame WfProcesarProductosExonerados y en este workflow vamos a crear dos parámetros:

  1. ProductosRecibidos: Colección de productos a procesar –> List<Producto>: Ingreso.
  2. ProductosExonerados: Colección de productos que están exonerados –> List<Producto>: Retorno.

Para crear la primera lista, seleccionamos en el tipo del argumento la opción Browse For Types. Luego nos aparecerá un diálogo en donde vamos a seleccionar – buscando – el tipo List<T>.

image

En esta lista procedemos a seleccionar el tipo que queremos asignarle a T, para esto procedemos a seleccionar de la lista desplegable la opción “Browse For Types” de nuevo. En esta opción seleccionamos la clase Producto.

image

Para la lista de retorno, solamente tenemos que expandir la lista del tipo y ya nos aparecerá disponible List<Producto> como tipo para elegir.

image

Ahora procedemos a crear el workflow. En este caso vamos a recibir la lista de productos – pProductosRecibidos – y la vamos a recorrer. Por cada producto vamos a preguntar si el producto esta exonerado, si es así procedemos a agregarlo a la nueva lista de retorno. El workflow completo se puede ver a continuación.

image

Es importante notar que para poder agregar los productos a la nueva lista, esta debe de ser instanciada antes de poder ser utilizada, tal y como se ve en la siguiente figura.

image

Igualmente es importante destacar que la estructura de ForEach debe de ser tipificada para que compile. Esto se logra cambiándole la propiedad TypeArgument del ForEach.

image

También se debe de utilizar la figura para agregar elementos a una colección. Esta figura debe de ser configurada con el ítem que se desea agregar –> en nuestro caso el item del foreach – y la colección a la que deseo agregar el ítem. También debo de agregar el tipo con el que va a trabajar la figura.

image

Ahora procedemos a trabajar en la consola. En primera instancia tenemos que crear la colección de productos que le vamos a enviar al workflow para que los procese.

image

Luego procedemos a crear la instancia del workflow y a pasarle los parámetros –> en este caso nuestra colección _productos. En la misma llamada se retorna la colección de productos ya procesados.

image

Seguidamente procedemos a convertir el parámetro de retorno en una lista y la procesamos.

image

El resultado al ejecutar el código anterior es el siguiente.

image

Etiquetas de Technorati: ,

10.20.2011

Aprendiendo WF parte 5: Clases como Parámetros

Continuando con la serie de post acerca de WF, en esta ocasión vamos a trabajar utilizando clases como parámetros. Esto desde el punto de vista arquitectura tiene mucho sentido porque nos va a permitir utilizar nuestras entidades de negocio como parámetros de los workflows que al final terminarán invocando nuestros componentes de negocio.

La clase Persona

Para este ejemplo vamos a utilizar una clase llamada persona, la cual se muestra a continuación:

image

El Workflow

Vamos a crear un nuevo Workflow en donde vamos a definir si una persona puede hacer el examen para tener permiso de conducir – licencia. Para esto vamos a recibir como parámetro una instancia de una persona y vamos a verificar la Edad de la persona, si la persona es mayor de 18 años entonces puede tomar el examen lo cual será indicado retornando en una variable booleana el valor verdadero, en caso contrario vamos a retornar falso.

Para agregar un workflow a la solución actual iniciamos agregando una nueva actividad al proyecto – recordemos que los workflows en sí son actividades que contienen otras actividades.

image

En el workflow recién creado vamos a crear un parámetro de entrada llamado pPersona del tipo Persona. Para tener acceso a este tipo desde el UI de parámetros de workflow, primero tenemos que compilar la aplicación, seguidamente procedemos a definir la variable y a asignarle el tipo vía la opción “Browse for Types”.

image

En la pantalla de selección de tipos buscamos la recién definida clase Persona.

image

Ahora procedemos con la definición del parámetro de retorno. En este caso haremos una variable llamada pRespuesta de tipo boolean.

image

Ahora procedemos a crear el workflow. Este decidirá en base a la edad de la persona si esta puede o no hacer el examen de manejo. El workflow se puede ver a continuación.

image

Como se ve en la ilustración anterior, usamos una figura “if” para determinar la edad de la persona y si esta es mayor de 17 años, entonces le asignamos con una figura “Assign” verdadero al resultado, en caso contrario le asignamos falso.

Invocando el workflow

Para invocar el workflow, debemos de crear una instancia de la clase Persona y enviarla vía el diccionario de parámetros al workflow. Además, debemos de recibir la respuesta vía el diccionario de respuesta del workflow.

image

Al ejecutarlo el resultado es el siguiente:

image

Etiquetas de Technorati:

10.15.2011

Aprendiendo WF parte 4: Parámetros de Salida

Continuando con el post anterior, ahora vamos a proceder a trabajar con los parámetros de retorno desde un workflow hecho en WF 4.

En el ejemplo anterior vimos como recibir parámetros desde el programa de consola, luego con el parámetro recibido procedimos a imprimir un mensaje en el workflow – un saludo. Sin embargo, desde la perspectiva de arquitectura de software, el uso de esta primitiva –WriteLine –rompe con una regla fundamental a la hora de trabajar con la separación de responsabilidades de cada capa, ya que hace que workflow que acabamos de crear dependa de la capa gráfica en donde vamos a publicar los mensajes; es decir, solamente vamos a poder utilizar este workflow en una aplicación de consola.

Los Workflows son Ajenos al UI

Pero el problema anterior no se debió haber presentado porque en realidad en una arquitectura de software, un workflow debe de ser independiente de la capa de presentación. Por esta razón vamos a modificar el workflow anterior para que construya el mensaje y lo retorne a la capa de presentación que lo este utilizando. Vamos a agregar una variable de salida al workflow para poder devolver el mensaje tal y como se ve en la siguiente figura:

image

En la variable pSaludo vamos a devolver el mensaje construido. Ahora vamos a modificar el workflow para que construya este mensaje de saludo, para esto debemos deshacernos de la figura de WriteLine y procedemos a utilizar una figura de asignación. El workflow se ve así:

image

Listo, ahora procedemos a recibir el saludo en la aplicación de consola – aunque podría ser desde cualquier otro tipo de aplicación como Web o WPF. Para esto creamos un diccionario similar a de los parámetros en donde vamos a recibir nuestras respuestas. Luego obtenemos el valor de la variable desde este diccionario e imprimimos el valor de la respuesta.

image

El resultado al ejecutar la aplicación anterior es el siguiente:

image

Etiquetas de Technorati:

10.13.2011

Aprendiendo WF parte 3: Parámetros de entrada

Un workflow normalmente se activa a través de un servicio o un componente de negocios. Este workflow por lo general recibe parámetros para poder llevar a cabo el proceso que se desea activar. En este workflow vamos a ver como enviarle parámetros a un workflow en WF.

Crear el Workflow

En primera instancia vamos a crear un workflow muy simple que recibe el nombre de una persona e imprime un saludo con este nombre. Lo primero que tenemos que hacer es crear el parámetro que recibe el workflow; para esto, vamos a crear un argumento de tipo string cuya dirección es “In”.

image

El siguiente paso es agregar una secuencia y una figura de “WriteLine” al workflow y configurarle el texto de la siguiente forma:

image

El workflow debería lucir como se ve a continuación:

image

Paso del Parámetro

Inicialmente, los parámetros se exponen vía propiedades dinámicas a través del workflow y esto permite que de una forma sencilla podamos invocarlo. El código para llevar a cabo esto desde una consola es el siguiente:

image

Si ejecutamos esta consola el resultado será el siguiente:

image

Aunque esta es una forma sencilla de pasar los parámetros, no es la más común a la hora de utilizar WF. Normalmente los parámetros se pasan vía un diccionario de datos a través del constructor de la instancia del tipo tal y como se puede ver en la siguiente figura. Nótese que la llave del elemento tiene que coincidir con el nombre del argumento que está esperando el workflow.

image

Etiquetas de Technorati:

10.09.2011

Creando un proyecto C# con el MSBuild

En la labor de crear un migrador de Oracle Forms a .NET me encontré con una tarea muy interesante: crear un proyecto en C# de forma dinámica, y compilarlo. En este post voy a compartir de forma simple como crear una pequeña aplicación de consola con un editor de texto, como crear un archivo de proyecto y como compilarlo.

La clase Hola en C#

La primera tarea que haremos es crear una clase que despliega un mensaje en la consola. Esta clase esta escrita usando Notepad2 y se presenta a continuación:

image

por supuesto que si quisiéramos podríamos compilar esta clase utilizando el compilador de C# – csc.exe – pero queremos crear dinámicamente el proyecto para agregar todas las clases y archivos necesarios al mismo y poder utilizarlo en Visual Studio.

El MSBuild

Aquí es donde entra el MSBuild. El MSBuild es una plataforma para construir – compilar – aplicaciones. Este contiene un esquema XML para el archivo de proyecto que controla como la plataforma de construcción procesa y construye el software.

Para nuestro proyecto vamos a utilizar el siguiente archivo de proyecto, el cual vamos a llamar proyecto.csproj:

image

Ítems

Los ítems son las entradas para el sistema de construicción, y normalmente se representan a través de archivos. Estos ítems se agrupan en grupos del mismo tipo. En el archivo de proyecto anterior creamos un ItemGroup con archivos de tipo Compile – hola.cs – dentro del mismo.

Targets

Agrupan tareas en un orden particular para que sean ejecutadas por el motor del MSBuild; en nuestro caso, creamos un Target que invoca el compilador de C# – csc.exe – para compilar cada uno de los archivos cs en el item group.

Compilación del Proyecto

Para compilar nuestro proyecto solamente tenemos que ir al command prompt de Visual Studio y digitar el siguiente comando:

image

Si el comando se ejecuta de manera exitosa entonces podremos ver el resultado en nuestro command prompt.

image

si vemos el contenido del directorio nos daremos cuenta que se ha creado un archivo con extensión exe. Si ejecutamos “hola” en el prompt veremos que nuestra aplicación se ejecuta de la forma correcta.

image

Etiquetas de Technorati:

10.04.2011

Como ver los comandos enviados al Entity Framework

Cuando utilizamos el Entity Framework constantemente nos preguntamos ¿ y que fue lo que se envió a la base de datos? A partir de esta pregunta surgen muchas herramientas tales como "profilers" comerciales - como eProf - , y el analizador de consultas de SQL Server o el de la base de datos que estemos utilizando. Sin embargo, estas soluciones pueden no ser suficientes porque pueden existir escenarios en donde sea necesario por seguridad o auditoría almacenar las sentencias SQL que se envían a la base de datos. Este post da solución a este problema.

Existe un tipo en el EntityFramework conocido como el ObjectSet<T>. Esta clase representa un conjunto de entidades sobre la cual se pueden ejecutar operaciones de eliminación, actualización, consulta, etc. El ObjectSet además tiene un método que se llama ToTraceString() el cuál nos permite obtener el comando enviado a la base de datos.

Para esto vamos a hacer un ejemplo sencillo donde vamos a consultar la tabla de consultores que vemos en el siguiente modelo del EF.

image

Si queremos obtener los consultores en la base de datos y a la vez ver la consulta enviada por parte del EF procedemos a ingresar el siguiente código.

image

El resultado a la hora de ejecutar la consulta anterior es el siguiente:

image

Etiquetas de Technorati:

10.02.2011

Aprendiendo WF parte 2

Continuando con esta serie de post acerca de Workflow Foundation, esta semana vamos a conversar acerca del manejo del hosting cuando utilizamos esta tecnología. Como recordarán en el post anterior, en ambos casos creamos una instancia del workflow utilizando una aplicación de consola, tal y como se puede apreciar en la siguiente imagen.

image

Al ser WF4 parte del framework de .NET se permite “hostear” y ejecutar un workflow en cualquier tipo de aplicación que este ejecutando el Framework de .NET – en este caso el 4.0. Podemos hostear un workflow como un servicio en WCF, en una aplicación ASP.NET, en una aplicación de consola, etc. Algo que siempre debemos considerar es que los workflows deben de ser independientes de el ambiente que los hostea, esto con el fin de permitir que estos puedan ser ejecutados e invocados desde cualquier tipo de consumidor.

El método Invoke de la clase WorfklowInvoker lo que haces es crear un workflow de manera sincrónica y retorna un diccionario de valores los cuáles representan los valores de retorno del workflow. Es importante destacar que la ejecución del workflow esta garantizada en el thread que lo invoca.

Si vemos la definición del método en el msdn, podemos ver que existen muchas versiones sobre cargadas del método; sin embargo, nosotros estamos utilizando la versión que recibe una actividad:

image

Y entonces surge la pregunta ¿No estamos enviando un workflow como parámetro? ¿ Porqué estamos utilizando una función que recibe una actividad? En realidad este es un concepto muy importante y es algo que tenemos que tener muy presente cuando utilizamos WF4. En WF4 los workflows son actividades que contienen otras actividades y por lo tanto cuando inicio un workflow utilizo la función que recibe una clase de tipo Activity, y dado que los workflows heredan de la clase Activity y gracias al polimorfismo, podemos enviar nuestro workflow como parámetro para este método.

Si vemos el código XAML del workflow que creamos en el ejemplo anterior – los workflows en WF4 son XAML – veremos que el nombre del workflow esta definido a través de la palabra reservada x:Class y para este caso el nombre del tipo es Workflow1 – para ver un workflow en xaml le damos botón derecho sobre el archivo y seleccionamos la opción ViewCode.

image

Etiquetas de Technorati:

9.30.2011

Aprendiendo WF parte 1

Una de las tecnologías que más utilizo y más me gusta de .NET es quizás una de las más subutilizadas es el Workflow Foundation. Por esta razón he decidido hacer una serie de post referente a esta tecnología con el fin de incentivar el uso de tan potente framework.

Introducción

El workflow foundation es un framework que nos permite diagramar procesos de negocio para orquestar componentes de negocio con lo cual podemos obtener una serie de beneficios tanto desde el punto de vista técnico como desde el punto de vista negocio. Entre los beneficios técnicos tenemos:

  • Los procesos gráficos son más simples de mantener.
  • Dado que el runtime del WF maneja mucho de las complejidades del framework es más simple aprovecharse de bondades tales como el paralelismo.
  • La facilidad para implementar servicios WFC a través de WF.

Entre lo más destacado desde el punto de vista negocios podemos mencionar:

  • Los analistas de negocio pueden participar más activamente de la definición y desarrollo del proceso
  • Los cambios a los procesos salen a producción más rápidamente.
  • Al exponer los procesos como servicios, permite que los mismos analistas de negocios estén conscientes de la posibilidad de reutilizar procesos de negocios ya existentes para crear nuevos procesos.

Desarrollando el primer workflow en WF

Los workflows de negocio están compuestos por actividades las cuales tiene diversas funcionalidades. Estas actividades en workflow foundation se representan tanto gráficamente como a través del código. En este primero post vamos a crear un workflow muy simple utilizando ambas presentaciones.

WF a través del diseñador

Para desarrollar nuestro primero ejemplo, vamos a crear una aplicación de consola del tipo workflow.

image

Ya en el workflow simplemente vamos a crear un flujo que simplemente escribe una hilera en la consola –> el típico hola mundo. El workflow se puede ver a continuación:

image

Este workflow simplemente tiene dos formas, una secuencia – que para este caso podría no ser necesaria ya que funciona como un contenedor secuencial de formas y en realidad la primitiva WriteLine podría funcionar sin la secuencia. Si ejecutamos este workflow el resultado se ve en la siguiente pantalla.

image

¿Y como funciona este workflow? En realidad toda la “magia” esta en el archivo program que se genera cuando creamos el proyecto, el cual vemos a continuación:

image

En el método Main, se invoca una nueva instancia del tipo Workflow1, la cual es la clase que representa nuestro workflow gráfico.

WF a través de código

Ahora vamos a construir el mismo workflow pero por código. Para esto vamos a hacer un proyecto de consola pero de los que normalmente hacemos para los ejemplos en el blog.

image

Como tenemos un proyecto normal de aplicación de consola, debemos agregar el assembly que contiene las actividades que pueden llegar a formar parte de nuestro workflow, incluso nuestro workflow es una actividad. Para esto procedemos a agregar una referencia a la librería System.Activities.

image

Ahora vamos a crear una clase que represente un workflow por código que simplemente escriba tal y como lo hicimos en el workflow gráfico el típico saludo de “Hola Mundo”. Esta clase la vamos a llamar WFSaludo y se presenta a continuación.

image

Para que la clase nos compile debemos agregar referencia a las siguientes librerías – si usan R#, la herramienta se las sugiere automáticamente:

image

Ahora vamos a invocar el workflow desde el método Main, tal y como lo hicimos con el workflow gráfico.

image

El resultado de ejecutar este workflow es el mismo que el anterior y se presenta a continuación.

image

 

Etiquetas de Technorati: ,

9.21.2011

Concurrencia y el Entity Framework – Parte 2

Continuando con el post anterior vamos a dar las soluciones que están al alcance de los que desarrollamos aplicaciones usando el Entity Framework. En este post (2 / 3 ) vamos a utilizar los timestamps para identificar si una columna ha cambiado.

Agregar columna timestamp

Inicialmente vamos a agregar una propiedad para tracking dentro de la entidad Consultor, esta propiedad será de tipo Byte[] y utilizará una anotación –> atributo <— del namespace del Entity Framework que le servirá para reconocer que esta columna debe ser parte de las sentencias Update y Delete en la parte del Where.

image

Hay que destacar que la base de datos original debemos eliminarla para que se recree de nuevo o modificarle la tabla consultor para que soporte el nuevo campo agregado. Si la opción es esto ultimo el campo a agregar debe lucir como el siguiente:

image

Ahora vamos a proceder a modificar el método Edit –> [HttpPost] del controller de Consultor.

image

Como podemos ver en el código anterior, tenemos que atrapar una excepción específica para saber si hubo un problema de concurrencia con el registro que estamos trabajando. El mensaje de error se agrega al ModelState y la llave del error se deja en blanco, lo que provoca que cuando se solicite de nuevo la vista actual con la tipificación del consultor, el mensaje de error se despliegue en la página – se puede encontrar más información acerca del ModelState en este link.

Tenemos también que agregar la nueva propiedad a la vista de edición del Consultor, en esto lo hacemos agregando un hidden field seguido del campo del Id.

image

Ahora si intentamos modificar un registro que ya fue modificado posteriormente a nuestra consulta, veremos el error de concurrencia aparecer en nuestra página.

Por ejemplo, si estamos editando el registro y queremos cambiarlo como se ve en la figura siguiente:

image

Pero otro usuario desde otro navegador hace el cambio y lo refleja en la base de datos antes de que yo haga el “submit” del mío:

image

Cuando yo intente modificar el registro en la base de datos, voy a recibir el siguiente error:

image

Etiquetas de Technorati: ,