6.19.2009

Podcast Driven Design (PDD)

En conjunto con Carlos Lone de Guatemala, hemos estado trabajando en la creación de una serie de podcast a los que hemos llamado “Podcast Driven Design (PDD)”. En estos programas, tratamos de discutir hacer de las tecnologías para desarrollar aplicaciones .NET y sobre todo tratamos de explicar un poco más a fondo cual es el rol de cada tecnología en nuestras aplicaciones.

Aqui les dejo el primer episodio que hemos grabado. Este episodio es un programa donde se discuten temas como Linq2SQL, Entity Framework  y los ORM’s en general. Espero les guste y esperamos sus comentarios

Episodio # 1 (ORM's y LINQ to SQL)

Descargar

6.14.2009

Versionando Aplicaciones – CastleWindsor – Parte 2

Tal y como lo mencioné en el post pasado, la forma más adecuada para manejar versionamiento de aplicaciones ( diversas funcionalidades por cliente dentro de una aplicación) es utilizando IoC. En este post voy a examinar como manejar el versionamiento utilizando la librería CastleWindsor – Windsor Container - como contenedor de IoC.

Para examinar los tres frameworks de IoC, voy a utilizar el mismos ejemplo. El ejemplo consiste en una interface para manejar alertas, la cual especifica en su contrato una propiedad para almacenar el mensaje y un método para enviar la alerta. Vamos a tener dos clases implementando este contrato, una que teoóricamente envía alertas por email, y otra por SMS. Vamos a tener además una clase para hacer búsquedas la cual enviará una alerta cada vez que se haga una búsqueda ( suponiendo que en la búsqueda van palabras que pueden ser consideras “peligrosas ). El diagrama de clases es el que se presenta a continuación:

image

Utilizando Castle Windsor

El Windsor Container es un contenedor de control de inversión el cual a grandes rasgos, extiende la funcionalidad de su homólogo en el mismo framework – MicroKernel – agregando soporte por configuración.

En este caso vamos a crear una aplicación de consola que contenga las clases y la interface antes mencionada y vamos a instanciar las alertas utilizando el IoC CastleWindsor.

Para poder utilizar CastleWindsor debemos agregar las referencias siguientes:

image

Seguidamente procedemos a crear la interface IAlert, la cual va a tener el contrato de la funcionalidad de la alerta:

image

El código de esta interface es el siguiente:

public interface IAlert
{
string Message { get; set; }
string SendAlert( );
}


El siguiente paso es crear la clase EmailAlert para enviar alertas por correo.



public class EmailAlert : IAlert
{
private string m_Message;

public string Message
{
get
{
return m_Message;
}
set
{
m_Message = value;
}
}

public string SendAlert( )
{
if (!string.IsNullOrEmpty(Message))
return Message;
return "Alerta enviada por mail";
}


}


Ahora vamos a crear la clase SMSAlert para “enviar” alertas a través de SMS.



public class SMSAlert : IAlert
{
private string m_Message;
public string Message
{
get
{
return m_Message;
}
set
{
m_Message = value;
}
}

public string SendAlert( )
{
if (!string.IsNullOrEmpty(Message))
return Message;
return "Enviando Alerta por SMS";
}
}



A continuación vamos a crear la clase SearchManager, la cual es la que realiza las búsquedas y dispara las alertas.



public class SearchManager
{
public IAlert Alert { get; set; }

public SearchManager( IAlert pAlert )
{
Alert = pAlert;
}

public string DoSearch( string criteria )
{
//Notificamos la búsqueda
if (Alert != null)
return Alert.SendAlert( );
return "Error!";
}
}


En primera instancia vamos a registar los componentes a instanciar desde el código ( algo que no tiene mucho sentido si se lo que se desea es versionar, pero es una buena forma de entender como funciona este contenedor). El código siguiente muestra como llevar a cabo esta tarea.



class Program
{
static void Main( string[] args )
{
IWindsorContainer contenedor = new WindsorContainer( );
contenedor.AddComponent("Email.Alert", typeof(IAlert), typeof(EmailAlert));
contenedor.AddComponent("Sms.Alert", typeof(IAlert), typeof(EmailAlert));


IAlert AlertaEnviada = contenedor["Email.Alert"] as EmailAlert;
//IAlert AlertaEnviada = contenedor["Sms.Alert"] as EmailAlert;

Console.WriteLine("Alerta: {0}", AlertaEnviada.SendAlert( ));

}
}



Primeramente, podemos ver que se instancia el contenedor de componentes, seguidamente registramos los componentes que queremos que esten disponibles para el contenedor, y por último instanciamos la clase que deseamos utilizar en el código. Como se puede ver en el proceso de crear la instancia, lo único que tenemos que hacer es pedirle al contenedor que me devuelva una instancia de la clase utilizando la llave que se utilizó para agregar la definición del componente al contenedor – en el ejemplo anterior Email.Alert y Sms.Alert. Al ejecutar la aplicación de consola recién creada obtenemos el siguiente resultado:



image



Seguidamente vamos a llevar a cabo esta instanciación y el registro de componentes via configuración, en donde el manejo versionamiento empieza a tener sentido.



Utilizando Archivos de Configuración


Por supuesto que el registrar componentes vía código, no es la forma en que podemos aprovechar este patrón para poder versionar nuestra aplicación. Lo que realmente buscamos, es poder registrar componentes sin recompilar la aplicación, y que la aplicación compilada busque los servicios en los contratos especificados vía configuración.



Para esto WindsorCastle tiene la posiblidad de registrar los componentes vía archivo de configuración, y al ser la aplicación de ejemplo una aplicación de consola, este archivo es el app.config. Para registrar los componentes vía archivo de configuración, tenemos que agregar los siguientes elementos a este archivo:



<?xml version="1.0" encoding="utf-8" ?>
<
configuration>
<
configSections>
<
section
name="castle"
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
</
configSections>
<
castle>
<
components>
<
component
id="Email.Alert"
service="PruebaCastleWindsor.IAlert, PruebaCastleWindsor"
type="PruebaCastleWindsor.EmailAlert, PruebaCastleWindsor" />

<
component
id="Sms.Alert"
service="PruebaCastleWindsor.IAlert, PruebaCastleWindsor"
type="PruebaCastleWindsor.SMSAlert, PruebaCastleWindsor" />
</
components>

</
castle>

</
configuration>


Como podemos ver, primero debemos crear una sección donde se registra el Handler de CastleWidows – llamada castle – y luego en la sección de componentes de castle procedemos a registrar nuestros componentes. En este caso, PruebaCastleWindsor es el namespace que estoy utilizando en la aplicación de ejemplo. Seguidamente procedemos a cambiar el método Main en el archivo Program.cs de la siguiente manera:



using System;
using Castle.Core.Resource;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;

namespace PruebaCastleWindsor
{
class Program
{
static void Main( string[] args )
{
IWindsorContainer contenedor = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
//IAlert AlertaEnviada = contenedor["Email.Alert"] as EmailAlert;
//IAlert AlertaEnviada = contenedor["Sms.Alert"] as EmailAlert;
IAlert AlertaEnviada = contenedor[typeof(IAlert)] as IAlert;
Console.WriteLine("Alerta: {0}", AlertaEnviada.SendAlert( ));
contenedor.Release(AlertaEnviada);
}
}
}


Primeramente, agregamos las referencias a las librerías necesarias para poder utilizar el contenedor vía configuración, seguidamente creamos la instancia del contenedor pero esta vez, le indicamos que busque el recurso de configuración en la sección llamada “castle”. Por último, invocamos el componente de la misma forma que hicimos en el código anterior, solo que esta vez estamos cargando la instancia por medio del tipo del servicio, igualmente puedo cargar la instancia utilizando la llave utilizada para registrar el componente en el archivo config. Al ejecutar el código anterior, el resultado es:



image Hay varias cosas que se pueden destacar de este resultado. Primero, veamos que la alerta que se envía es la de correo, pero ¿por qué? bueno, esto sucede por que en el archivo de configuración EMailAlert fue el primero componente registrado, y como no le indicamos al contenedor que tipo instanciar, el automáticamente toma el primero en la lista.



<components>



<component id="Email.Alert" service="PruebaCastleWindsor.IAlert, PruebaCastleWindsor" type="PruebaCastleWindsor.EmailAlert, PruebaCastleWindsor" />



<component id="Sms.Alert" service="PruebaCastleWindsor.IAlert, PruebaCastleWindsor" type="PruebaCastleWindsor.SMSAlert, PruebaCastleWindsor" />



</components>



Seguidamente podemos ver que aunque instanciamos un tipo específico, en ningún momento atamos el código con la alerta de correo, ni con la alerta de SMS, por lo que trabajando con los servicios – interfaces – podemos ejecutar la instancia del componente que deseamos.



Seleccionando la Instancia de la Clase que Deseamos Crear


Ahora le vamos a decir al buscador que seleccione vía configuración, como debe enviar la alerta, ya sea por correo o por SMS. Para lograr esto, vamos a registrar la clase SearchManager en los componentes de CastleWindsor, y vamos a crear la instancia desde el contenedor. Primeramente, agregamos SearchManager al conjunto de componentes registrados en CastleWindsor.



<castle>
<
components>
<
component
id="SearchManager"
type="PruebaCastleWindsor.SearchManager, PruebaCastleWindsor"
/>

<
component
id="Email.Alert"
service="PruebaCastleWindsor.IAlert, PruebaCastleWindsor"
type="PruebaCastleWindsor.EmailAlert, PruebaCastleWindsor" />

<
component
id="Sms.Alert"
service="PruebaCastleWindsor.IAlert, PruebaCastleWindsor"
type="PruebaCastleWindsor.SMSAlert, PruebaCastleWindsor" />
</
components>

</
castle>



El siguiente paso, es instanciar la clase SearchManager desde el contenedor y llamar al método DoSearch, que al mismo tiempo, es el método que envía la alerta.



static void Main( string[] args )
{
IWindsorContainer contenedor = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
SearchManager manager = contenedor[typeof(SearchManager)] as SearchManager;
Console.WriteLine(manager.DoSearch("búsqueda"));

}


De nuevo, si ejecutamos este código el resultado va a ser igual al resultado anterior como podemos ver en esta imagen.



image La razón es igual a la anterior, el componente EmailAlert esta registrado primero que el SMSAlert, y como podemos ver en la siguiente imagen, cuando se crea la instancia del SearchManager, CastleWindsor crea una instancia del parámetro que se desea tomando el orden de registro del componente, en este caso, tomando la clase EmailAlert.



image



Seleccionando la Alerta a Enviar


Por último, vamos a seleccionar vía configuración cual es la alerta que queremos enviar desde la clase SearchManager; esto desde nuestro problema de versionamiento sería como instanciar la clase del cliente que corresponde simplemente configurandola desde el archivo de configuración.





<component
id="SearchManager"
type="PruebaCastleWindsor.SearchManager, PruebaCastleWindsor" >
<
parameters>
<
Alert>${Sms.Alert}</Alert>
</
parameters>

</
component>



En esta ocasión, estamos creando un elemento parameters que va a contener la colección de parámetros con que queremos instanciar la clase SearchManager. En este caso queremo enviarle el tipo de alerta que queremos trabajar, por lo que creamos una etiqueta con el nombre de la propiedad que va a almacenar nuestra instancia de Alerta, en nuestro caso se llama Alert. Vamos a cambiar un poco la clase, por que aunque podemos utilizar el parámetro del contructor, no es necesario, ya que CastleWindsor busca la propiedad especificada en la etiqueta, y le crea una instancia con el contenido de la misma, la cual en este caso nos dice que quiere una instancia del componente registrado con el id “Sms.Alert”.



namespace PruebaCastleWindsor
{
public class SearchManager
{
public IAlert Alert { get; set; }

public SearchManager( ) { }

public string DoSearch( string criteria )
{
//Notificamos la búsqueda
if (Alert != null)
return Alert.SendAlert( );
return "Error!";
}
}
}


Si ejecutamos el código anterior, vemos que el mensaje lanzado desde Alert.SendAlert no es el de la alerta por mail como ocurria antes por defecto, si no que es el de alerta por SMS, la cual es la que estamos configurando por parámetro. De nuevo, el código de la clase program no se cambia y el resultado de la ejecución es el siguiente:



image



Conclusión


La idea con este patrón es poder crear instancias de clases por medio de configuración y polimorfismo. Como vimos en este post, esto es posible a través del uso de CastleWindsor, el cual nos permite crear instancias de clases configuradas en el archivo App.config. Esto nos permite crear interfaces con el core de funcionalidades a implementar, e implementar clases que lleven funcionalidad específica para el cliente, las cuales se instancia de acuerdo a lo que se necesite por la aplicación y lo que definamos en el archivo config. En el siguiente post vamos a llevar a cabo la misma tarea, pero utilizando Autofac.



Technorati Tags: ,,

6.12.2009

Versionando Aplicaciones en .NET - Introducción – Parte 1

En muchas ocasiones, me encuentro en diferentes empresas con la finalidad de ayudar a desarrollar una nueva aplicación basado en una versión anterior de la misma utilizando arquitecturas, frameworks y componentes que ayuden a mejorar la velocidad de desarrollo, faciliten el mantenimiento de la misma, y permitan adoptar nuevas funcionalidades no disponibles en la versión anterior. En medio de estos procesos, en la mayoría de los casos, y sobre todo en las empresas que venden su software a terceros, me encuentro con un problema que parece ser muy común:

Como manejar el versionamiento de mi aplicación, si tengo varios clientes y cada cliente tiene formas diferentes de llevar a cabo algunos de sus procesos

Esto sin duda alguna es todo un reto, ya que implica que vamos a tener una sola versión de la aplicación con comportamientos diferentes.

En el pasado – y aún ahora – muchas empresas lo que hacen es crear una copia del proyecto para cada cliente, lo que conlleva a que no se puedan lanzar nuevas versiones del producto, o al menos del corazón de la funcionalidad del producto, por que la empresa terminará teniendo una versión para cada cliente, por lo tanto terminará teniendo tantos productos como clientes tiene. En otras ocasiones, sobre la misma aplicación se empieza a agregar la funcionalidad variante, dividida por estructuras if – else o por algún otro mecanismo que permita esta separación del código; esto por supuesto termina complicando los escenarios de desarrolla en una forma desproporcionada, porque algo que resulta ser un pequeño cambio para un cliente quiebra un montón de funcionalidad en otro cliente.

La pregunta obvia que surge es entonces: ¿Cómo puedo hacer que mis sistemas se desarrollen con el versionamiento para las mismas de una forma más manejable y más simple? La respuesta también es simple: IoC - inversion of control container. Un IoC es un patrón que en conjunto con el Dependency Injection ayuda a ensamblar componentes desde diferentes proyectos en  una aplicación funcional. El patrón en sí se enfoca en como crear instancias de las clases y componentes que necesitamos en tiempo de ejecución sin tener que recompilar y reinstalar la aplicación de nuevo para instanciar otra clase diferente a la definida en la compilación inicial. Información más detallada de el patrón en sí se puede encontrar en la página de Martin Flower.

Existen muchos IoC disponibles en el mercado para su uso libre en la plataforma .NET, y en esta serie de post voy a dedicarme a mostrar como funcionan algunos de estos componentes – los que a mi gusto son los más conocidos. Los IoC que estaré analizando son CastleWindsor, Autofac y Unity Application Block.

En el siguiente post estaré analizando CastleWindsor.

Technorati Tags: ,

6.02.2009

Seleccionando un Ítem en el DataGrid del WPF Toolkit

En un post anterior, mostramos como ligar el DataGrid del WPF toolkit a una colección de entidades generadas en el entity framework vía una capa de lógica de negocios. En este post vamos a obtener la fila seleccionada en el grid por parte del usuario y lo vamos a desplegar en una ventana en modo diálogo.

En este caso, vamos a presentar el usuario seleccionado con doble clic del mouse sobre el registro deseado en el DataGrid del toolkit de WPF. Pero antes de llevar a cabo esta tarea, tenemos que preparar la pantalla en la cual vamos a presentar los detalles del usuario. Para este ejemplo, vamos a utilizar la pantalla DetalleUsuario.xaml utilizada también en un post anterior para agregar usuarios a la base de datos. 

Lo primero que vamos a hacer es crear un constructor en la pantalla que me permita recibir el usuario como parámetro para poder desplegarlo. Una vez recibida la entidad usuario, procedemos a asignarlo a cada uno de los componentes que representan los atributos de la entidad en la pantalla – existen varias formas de hacer databinding en WPF, en este caso vamos a usar la que a mi criterio es la más simple de entender, en post posteriores vamos a ver las diferentes formas de hacer databinding en WPF. El código para llevar a cabo esta tarea es el siguiente:

public DetalleUsuario( )
{
InitializeComponent( );
}

public DetalleUsuario( Usuario usuario )
{
InitializeComponent( );
txtNombre.Text = usuario.Nombre;
txtApellido1.Text = usuario.Apellido1;
txtApellido2.Text = usuario.Apellido2;
txtEmail.Text = usuario.Email;

}



Seguidamente vamos a crear un manejador para el evento doble clic del DataGrid de usuarios en la pantalla AdministracionDeUsuarios.xaml. Para llevar a cabo esta tarea, marcamos el grid, vamos a las propiedades del mismo, y seleccionamos el botón con un ícono de rayo en el tool bar de las propiedades, esto presentará los eventos disponibles del control. Por último buscamos el evento MouseDoubleClick y le damos doble click para que genere el manjeador del evento automáticamente.



image



Una vez generado el handler del evento procedemos a codificar la selección del ítem y la invocación de la pantalla que presenta el detalle del ítem seleccionado.



private void dgUSuarios_MouseDoubleClick( object sender, System.Windows.Input.MouseButtonEventArgs e )
{
Usuario usuarioSeleccionado = dgUSuarios.SelectedItem as Usuario;
DetalleUsuario detalle = new DetalleUsuario(usuarioSeleccionado);
detalle.ShowDialog( );
}


Como podemos ver en el código anterior, la propiedad del grid que nos devuelve el row seleccionado es SelectedItem. En esta misma línea convertimos la fila seleccionada al tipo del objeto que queremos obtener, esto con el operador as.  Este operador tiene la ventaja de que trata de convertir la fila al objeto seleccionado, y si no puede llevar a cabo la conversión, establece la variable usuarioSeleccionado con un valor de null. En este caso la conversión se va a dar, dado que el datagrid esta ligado a una colección – lista – de entidades de usuario. Por último creamos la instancia de la forma donde vamos a presentar el detalle, pero utilizamos el constructor que acabamos de crear, pasándole el usuario obtenido de la selección del Datagrid. Para finalizar, presentamos la pantalla con el detalle.



image







5.20.2009

Alternativas para Iniciar con una Arquitectura Orientada a Servicios - SOA

Cuando en una empresa se habla de establecer una arquitectura orientada a servicios surgen muchas dudas respecto a como implementar este tipo de arquitectura. Una de las primeras preguntas que me hacen dentro de la organización cuando llego a ayudar en este tipo de tareas es:

Pero si al prinicipio vamos a tener unos cuantos servicios, por que tenemos que comprar un ESB, que por lo general cuesta mucho dinero.

Efectivamente, una de las principales limitantes a la hora de implementar una arquitectura orientada a servicios – aparte de las limitaciones técnicas – es la compra del software requerido para poder iniciar en SOA.

Normalmente, las empresas empiezan teniendo unos pocos servicios Web, los cuales brindan información ya sea a lo interno o a lo externo; estos servicios se hostean en el IIS. Aunque suene tentador, el hecho de tener solamente servicios web que son consumidos por clientes internos y externos, no implica que tengamos una arquitectura SOA; en realidad estamos creando una arquitectura punto a punto, en donde los clientes consumen directamente los servicios expuestos y quedan totalmente dependientes de la configuración de estos servicios; ya que por ejemplo, si cambian el servidor donde se hostean estos servicios, los clientes tienen que ser actualizados o no funcionarán del todo.

Ahora, conforme crecen la cantidad de servicios que estamos utilizando, empieza a crearse la necesidad de darles seguimiento, de tener un inventario para saber cuales servicios tengo disponibles y puedo reutilizar, de tener métricas de los servicios para poder medir mis SLAs con otros clientes, y muchas otras características típicas de una arquitectura SOA las cuáles nos indican que es hora de ir pensando en un ESB – ver el post de ESB para entender más a fondo que es un ESB – La pregunta que surge es ¿ Cuando debo migrar a un ESB ? ¿por que tengo que pasar de un modelo donde solo tengo que preocuparme por el IIS a un modelo donde tengo que tener otro servidor y debo comprar Biztalk Server y agregarle el ESB guidance? ¿ Por qué no existe un paso intermedio entre ambos, que me de el Governance necesario para poder iniciar con mi arquitectura SOA para poder demostrarle a la gerencia los beneficios de esta arquitectura?

Estas preguntas son totalmente válidas y aplican practicamente en cualquier tecnología sobre la cual estemos interesados en “montar” una arquitectura orientada a servicios. En general cuando me hacen este tipo de preguntas, me pregunto por que no existe un contenedor liviano para ese tipo de soluciones.

Pues resulta que ahora, el equipo de Microsoft Services SOA Solution Team ha creado un producto que viene a llenar ese vacío. Este producto es algo así como el paso intermedio entre la arquitectura punto a punto y la arquitectura SOA en toda su expresión, utilizando un ESB, orquestando servicios y todos los demás beneficios que vienen con una arquitectura orientada a servicios – bien aplicada. Esta herramienta esta en versión CTP y se llama el Microsoft Service Engine – MSE. Esta herramienta es una herramienta para facilitar la adopción de SOA en la empresa, todo a través de algo que se conoce como virutalización de servicios. El MSE esta construida sobre WCF y la plataforma de Windows Server. Se integra de forma natural con Biztalk y el ESB Guidance para cuando en etapas posteriores se desea aumentar la capacidad de governance, ruteo, transformación, etc.

El siguiente screen shot es una muestra de este tool.

MSE SOA

Este tool tiene otras 2 ventajas externas a lo técnico: Es Open source y es gratis. El sitio web donde se puede obtener información al respecto esta aquí en codeplex.

En post posteriores voy a profundizar acerca de las funcionalidades de esta herramienta, como configurarlo y como ponerlo a funcionar para poder adoptar una arquitectura SOA dentro de nuestras organizaciones.

Technorati Tags: ,,,

5.14.2009

Personalizando el DataGrid del WPF ToolKit

En el post pasado, creamos una interface gráfica para exponer todos los usuarios que están registrados en nuestro sistema de ejemplo. Esta pantalla estaba compuesta por un grid que mostraba esta información. El grid utilizado, es el grid del WPF Toolkit, el cuál contiene un conjunto de controles sumamente útiles que podemos utilizar de forma gratuita en nuestras aplicaciones desarrolladas con WPF.

En este post vamos a modificar esta pantalla para que el datagrid solo nos muestre los datos relevantes y no todo lo que nos devuelve el objeto desde la entidad proveniente desde el EF. Además vamos cambiar la forma en que luce el grid modificando sus propiedades visuales desde el código XAML.

La ventana en el post anterior lucía de la siguiente manera:

image

El primer cambio que le vamos a hacer al datagrid es mostrar solamente las columnas que le interesan al usuario de la aplicación, por lo tanto en este caso vamos a eliminar las columnas relacionadas con EF, tales como las relaciones y el EntityState, además vamos a eliminar la columna de borrado lógico Activo. Para lograr esto primeramente debemos poner la propiedad AutoGenerateColumns en falso.

<my:DataGrid Margin="12,51,21,27" Name="dgUSuarios" AutoGenerateColumns="False">


Seguidamente tenemos que definir las columnas que deseamos ligar al grid desde el resultado del método de consulta creado en la lógica de negocios. Esto se logra indicandole a la propiedad Binding a cual propiedad de la entidad devuelta debe de ligarse, tal y como lo muestra el siguiente código:



<my:DataGrid.Columns>
<
my:DataGridTextColumn Header="Id" Binding="{Binding Id}" IsReadOnly="True" />
<
my:DataGridTextColumn Header="Nombre" Binding="{Binding Nombre}" IsReadOnly="True" />
<
my:DataGridTextColumn Header="Primer Apellido" Binding="{Binding Apellido1}" IsReadOnly="True" />
<
my:DataGridTextColumn Header="Segundo Apellido" Binding="{Binding Apellido2}" IsReadOnly="True" />
<
my:DataGridTextColumn Header="Correo Electrónico" Binding="{Binding Email}" IsReadOnly="True" />
</
my:DataGrid.Columns>


Ahora vamos a pintar cada una de las filas con un color alternativo, en este caso, una fila de un color verde en gradiente y la siguiente de un color verde sin gradiente. El código XAML para lograr esto es el siguiente:



<my:DataGrid Margin="12,51,21,27" Name="dgUSuarios" AutoGenerateColumns="False" 
RowBackground="#FF70947A" AlternatingRowBackground="{StaticResource GradienteVerde}">


El gradiente verdes esta en los recursos del grid, es decir en el <Grid.Resources> y su contenido es el siguiente:



<LinearGradientBrush x:Key="GradienteVerde" EndPoint="1,0.5" StartPoint="0,0.5">
<
GradientStop Color="#FF227D2C" Offset="0"/>
<
GradientStop Color="#FF046B0E" Offset="1"/>
</
LinearGradientBrush>



La pantalla debe de lucir de la siguiente manera:



image Por último vamos a cambiarle el estilo al header del grid. El primer paso para lograr esto, es crear un estilo para poder asignarselo al grid. El estilo a utilizar lo vamos a definir en el archivo app.xml en la seccion de recursos de la aplicación.



<Application.Resources>
<
LinearGradientBrush x:Key="GridBackGround" EndPoint="1,0.5" StartPoint="0,0.5">
<
GradientStop Color="#FF000000" Offset="0"/>
<
GradientStop Color="#FF121111" Offset="1"/>
<
GradientStop Color="#FF605D5D" Offset="0.50"/>
</
LinearGradientBrush>
<
Style x:Key="HeaderStyle" TargetType="{x:Type Primitives:DataGridColumnHeader}">
<
Setter Property="VerticalContentAlignment" Value="Center" />
<
Setter Property="Background" Value="{StaticResource GridBackGround }" />
<
Setter Property="Foreground" Value="Orange" />
</
Style>
</
Application.Resources>



Como podemos ver en el estilo, las propiedades de background y foreground han sido cambiadas para que el header el background del header se vea de acuerdo al gradiente GridBackGround y el foreground se establece de color naranja.



Seguidamente lo agregamos el estilo al grid.



ColumnHeaderStyle="{StaticResource HeaderStyle}" 


Para lograr esto, establecemos la propiedad ColumnHeaderStyle con el valor del estilo que definimos en el bloque de código anterior.



La pantalla de resultado es la siguiente:



image



Technorati Tags: ,,

5.06.2009

El Entity Framework en una Arquitectura n-layer – Parte 4

En el post anterior iniciamos el desarrollo de la capa de UI utilizando WPF como tecnología. En este post vamos a continuar agregando funcionalidad al UI del sistema que estamos desarrollando.

En esta oportunidad, vamos a agregar una pantalla para ver todos los usuarios que hemos insertado dentro de la aplicación.

Creando la Pantalla de Administración de Usuarios

El primer paso es crear una nueva pantalla en el proyecto y llamarla AdministracionDeUsuarios. Esta pantalla va a tener un grid el cual nos va a presentar todos los usuarios que existen en nuestra aplicación. El grid que vamos a utilizar es el DataGrid del toolkit de WPF. A este datagrid le vamos a llamar dgUsuarios. Una vez creada la pantalla esta lucirá de la siguiente forma:

image

El siguiente paso es llenar el datagrid con los datos de usuarios que tenemos incluidos en nuestra base de datos. Para lograr esto vamos a utilizar el método ObtenerUsuarios de nuestra clase de lógica de negocios para el usuario. El código para llevar a cabo esta tarea es el que se presenta a continuación:

using System.Windows;
using LogicaDeNegocios;

namespace Cliente_WPF
{
public partial class AdministracionDeUsuarios : Window
{
public AdministracionDeUsuarios( )
{
InitializeComponent( );
}

private void Window_Loaded( object sender, RoutedEventArgs e )
{
UsuarioBL usuarioBL = new UsuarioBL( );
dgUSuarios.ItemsSource = usuarioBL.ObtenerUsuarios( );

}
}
}



Como se puede ver en el código anterior, solamente necesitamos crear una instancia de la clase UsuarioBL y ligar el datagrid con los datos que nos retorna el método ObtenerUsuarios el cual definimos en el post 2 de esta serie. Si ejecutamos la aplicación poniendo como forma de arranque la forma recién creada el resultado será el siguiente:



image



Como podemos ver en la imagen anterior, no solo se presentan los datos propios de la entidad en el grid, si no las relaciones existentes entre el usuario y el historial de casos de uso, el estado de la entidad que es utilizado para persistir cambios en el back end, y la llave de la entidad.



En el próximo post vamos a trabajar mejorando la presentación de este datagrid.



Technorati Tags: ,,,

5.04.2009

El Entity Framework en una Arquitectura n-layer – Parte 3

En los posts anteriores creamos la capa para la lógica de negocios y la capa de acceso a datos utilizando el entity framework. En este post, vamos a crear la capa de presentación de la aplicación de ejemplo utilizando WPF.

El primer paso es crear un nuevo proyecto dentro de la solución en la cual hemos venido trabajando. El proyecto a crear es una aplicación WPF.

image

Seguidamente, eliminamos la forma que se crea por defecto, y creamos una nueva pantalla. En este caso, vamos a crear una pantalla para agregar un usuario. Como podemos ver en el primer post, un usuario tiene básicamente los siguiente campos:

  • Id
  • Nombre
  • Apellido1
  • Apellido2
  • Email
  • Activo.

De estos campos, el Id es autogenerado y el campo de activo es para borrado lógico por lo que en la inserción por defecto, el campo se guarda con un valor de “Y”.

La pantalla que vamos a crear por lo tanto deberá lucir como se ve en la siguiente figura:

image Seguidamente vamos a agregar el código necesario para agregar la entidad ingresada en la forma, pero antes de esto, debemos agregar una referencia a la capa de lógica de negocios y a la capa de acceso a datos. A esta última la tenemos que agregar por que las entidades son el “medio de transporte” entre las capas, y como no tenemos una capa de entidades separada, entonces tenemos que agregarla desde la capa de acceso a datos. Además se debe de agregar una referencia a la librería System.Data.Entity. El código lucirá de la siguiente forma:

using System.Windows;
using CapaDeAccesoADatos;
using LogicaDeNegocios;

namespace Cliente_WPF
{
public partial class DetalleUsuario
{
public DetalleUsuario( )
{
InitializeComponent( );
}
private void btnOk_Click( object sender, RoutedEventArgs e )
{
Usuario usuario = new Usuario( );
usuario.Nombre = txtNombre.Text;
usuario.Apellido1 = txtApellido1.Text;
usuario.Apellido2 = txtApellido2.Text;
usuario.Email = txtEmail.Text;
usuario.Activo = "Y";
UsuarioBL usuarioBL = new UsuarioBL( );
usuarioBL.AgregarUsuario(usuario);

}
}
}



Como podemos ver, lo único que hacemos es crear una entidad, crear una instancia de la clase usuario de la lógica de negocios e invocar el método agregar usuario pasando de parámetro la entidad del usuario recién creada. Este código, además de simple, es sencillo de mantener y permite que todos los desarrolladores que estén trabajando en el proyecto, tengan un estilo similar para programar, lo que facilita el hecho de que una persona no este disponible para modificar o agregar funcionalidad a una pantalla.



Si ejecutamos la pantalla anterior, veremos la siguiente pantalla en ejecución:



image



Si ingresamos datos, y le damos ok, vamos a recibir el siguiente error de parte del entity framework:




The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid.




Esto quiere decir que el entity framework no esta encontrando el conection string para pegarse a la base de datos. Este connection string se encuentra en el archivo app.config de la librería de acceso a datos; pero en este caso, como no tenemos configurada la salida de todos los proyectos al mismo directorio – algo de lo que vamos a ir conversando en post posteriores – entonces la aplicación no lo logra localizar. Para solucionar este problema de forma rápida – y temporal -  debemos simplemente agregar un archivo app.config al proyecto del cliente WPF y copiar el connection string desde el app.config de la capa de acceso a datos.



El primer paso es agregar el archivo config al cliente de WPF.



image



Seguidamente copiamos desde el archivo app.config de la capa de acceso a datos, el string de conexión al archivo recién creado



<connectionStrings>
<
add name="UseCasesEntities" connectionString="metadata=res://*/UseCasesModel.csdl|res://*/UseCasesModel.ssdl|res://*/UseCasesModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=diego-pc\sqlserver2008;Initial Catalog=UseCases;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
</
connectionStrings>


Seguidamente, procedemos a ejecutar la aplicación y a insertar los usuarios que vayamos a necesitar.



En el siguiente post, vamos a crear una pantalla para que se nos muestre a través de el DataGrid del toolkit de WPF, todos los usuarios ingresado en la base de datos.



Technorati Tags: ,,,

4.26.2009

El Entity Framework en una Arquitectura n-layer – Parte 2

En el post anterior, iniciamos el desarrollo de una aplicacion n-layer utilizando en Entity Framework. En el post mencionado definimos y construimos la capa de acceso a datos la cual esta compuesta principalmente por el Entity Framework – aunque como veremos en futuros post, esta capa se va a extender con clases que le agrega funcionalidad el Entity Framework. En este post vamos a construir la capa de lógica de negocios para la aplicación que estamos desarrollando.

La capa de negocios es la capa en la cual vamos a crear los métodos unitarios que llevan a cabo las tareas correspondiente de cada una de las entidades. Estas tareas incluyen desde las operaciones CRUD – create, retrieve, update, delete – hasta procesos de negocios más elaborados.

Para crear esta capa de negocios, vamos a crear una librería utilizando los mismos pasos que hicimos en el post anterior, pero vamos a llamar la libreria como LogicaDeNegocios.

image Al igual que hicimos en la librería de la capa de acceso a datos, vamos a eliminar la clase que es creada por defecto cuando creamos el componente. La solución ahora debería lucir así:

image Seguidamente vamos a crear las clases de lógica de negocios para poder llevar a cabo operaciones que se requieran para cada entidad. En este caso, vamos a crear la clase de lógica de negocios para la entidad Usuario. Para crear esta clase, le damos click derecho sobre el proyecto de lógica de negocios y seleccionamos agregar nuevo ítem –> Agregar Clase. En el diálogo de agregar clase escribimos UsuarioBL como nombre de la clase, para poder identificar la clase de lógica de negocio para el usuario en las capas de presentación que vayamos a crear o incluso en la capa de servicios si deseamos crear una para permitir que nuestra funcionalidad de negocios se pueda acceder a través de servicios.

image El siguiente paso es agregar una referencia a la capa de acceso a datos para así poder tener visibilidad de las operaciones existentes dentro del modelo de entidades creado en esa librería. Para lograr esto, le damos click derecho al proyecto de lógica de negocios y seleccionamos la opción agregar referencia del menu contextual. En el dialogo de agregar referencias seleccionamos la cejilla de proyectos y escojemos el proyecto para capa de acceso a datos.

image La referencia debe poder verse en la carpeta de referencias del proyecto como se muestra a continuación.

imageUna vez agregada la referencia, procedemos a agregar el uso de la librería en la clase recién creada. Esto se logra a través de la instrucción using, seguidamente creamos una propiedad automática para tener acceso al modelo de entitdades que creamos anteriormente en la capa de acceso a datos.

imageComo se puede ver en la figura anterior, es requerido agregar la librería System.Data.Entities para poder hacer uso de las entidades presentes en la capa de acceso a datos. En post posteriores vamos a analizar con un poco más de profundidad el entity framework y estos detalles. Para agregar esta librería seguimos el mismo proceso que llevamos a cabo anteriormente para agregar la referencia a la capa de acceso a datos, solo que esta vez vamos a buscar la librería en la cejilla de .NET.

image Una vez agregada esta referencia, la clase actual para manejar la lógica de de negocios del usuario ya compila.

image

Un aspecto a destacar, es que agregamos una propiedad dinámica para tener acceso al modelo de entidades que acabamos de agregar desde la capa de acceso a datos, y además instanciamos el modelo de entidades generado desde el constructor de la clase. Este comportamiento puede no ser el deseado ya que puede producirnos trabajo extra a la hora de agregar relaciones que se obtienen desde otras clases de lógica de negocios por que cada clase va a venir de diferentes instancias del modelo, es decir desde diferentes contextos. En el post de como extender y mejorar el EF en una arquitectura n-layer vamos a ver cuales pueden ser las posibles soluciones para manejar estos casos.

Seguidamente procedemos a crear los métodos principales de CRUD en la lógica de negocios. Primeramente vamos a crear el método para agregar un usuario.Este método recibe una entidad del tipo Usuario, y la agrega al contexto instanciado utilizando el método generado AddToUsuario. Finalmente, procedemos a persistir los cambios en la base de datos utilizando el metodo SaveChanges.

image En muchas ocasiones surge la pregunta, ¿por qué recibir un usuario y no los campos para agregar a la entidad? La respuesta esta relacionada con la adaptabilidad al cambio de parte de la aplicación. Puede ser que en un futuro se requiera quitar o agregar campos a la entidad usuario; si estamos utilizando lo campos en lugar de una entidad, vamos a tener que modificar todos los métodos donde interactuamos con la entidad para modificar, actualizar, seleccionar, etc. Sin embargo, si utilizamos una entidad, los puntos que varían son la entidad, el UI en donde construimos la entidad y la capa de acceso a datos donde agregamos los campos al repositorios – si estamos usando el EF, no se requieren cambios en la capa de acceso a datos ya que el EF actualiza los métodos desde el modelo – con lo que nuestra aplicación es más fácil para modificar.

Seguidamente procedemos a crear los métodos necesarios para obtener todos los usuarios que existen en la base de datos, y el método que me retorna un usuario en específico.

Inicialmente agregamos la referencia a la librería System.Linq, esto para tener acceso a los métodos de extensión

using System.Collections.Generic;
using CapaDeAccesoADatos;
using System.Linq;


Seguidamente creamos los métodos mencionados anteriormente. En este caso vamos a utilizar la sintaxis del EF para acceder a los datos. En post posteriores vamos a utilizar LinqToEntities para llevar a cabo las mismas tareas.



public List<Usuario> ObtenerUsuarios( )
{
var usuarios = ModeloEntidades.Usuario;
return usuarios.ToList( );
}

public Usuario ObtenerUsuario( int id )
{
var usuario = ModeloEntidades.Usuario.Where(u => u.Id == id).FirstOrDefault( );
return usuario;
}



Con estos métodos ya tenemos un conjunto de funcionalidad suficiente para poder trabajar con nuestra capa de UI. Digo suficiente por que por supuesto faltan los métodos para actualizar y borrar usuarios, además los correspondientes métodos para asociar los usuarios a las entidades correspondientes. Estos métodos los vamos a agregar en futuros post.



La solución de la aplicación debe de lucir de la siguiente manera:



image



En el próximo post vamos a crear la capa de UI utilizando WPF.



Technorati Tags: ,,

4.19.2009

El Entity Framework en una Arquitectura n-Layer – Parte 1

En el post anterior acerca del Entity Framework en una arquitectura n-layer, describí el rol que juega el EF en una arquitectura n-layer. En este post vamos a crear un ejemplo para mostrar como se plasma en código las ideas expuestas en el post anterior.

En este caso, vamos a trabajar en el desarrollo de una “mini” aplicación que administra los casos de uso de n empresas – al menos desarrollar un poquito de funcionalidad de la aplicación para ilustrar los conceptos expuestos.

La Base de Datos

El primer paso es crear una base de datos para persistir la información de los proyectos. Vamos a crear una base de datos utilizando SQLServer2008. Esta base de datos se llamará UseCases. El diagrama inicial de la base de datos es el siguiente.

image

En este caso, vamos a decir que una empresa puede tener varios proyectos, y que cada proyecto tiene muchos casos de uso. Cada caso de uso tiene un historial de acciones que se graba cada vez que se realiza un cambio en el caso de uso ( esto suponiendo una base de datos completa, en donde se guardan los diferentes flujos del caso de uso, sus actores, etc). Por último, cada registro del historial de cambios tiene un usuario asociado que es precisamente el que realizó el cambio.

Desarrollando la Solución

Para el desarrollo de la solución vamos a utilizar Visual Studio 2008 SP1. El primer paso es crear una solución vacía para ir agregando los diversos proyectos que vamos a ir requiriendo en el desarollo de la aplicación. Para crear una solución vacía seleccionamos: new project –> visual studio solutions –> Blank Solution.

image

Creando la capa de Acceso a Datos

Una vez que tenemos la solución, vamos a crear la capa de acceso a datos ( que por lo general es el primer bloque que se crea cuando se realiza un proyecto con arquitectura n-layer). Para agregar el proyecto, seleccionamos con el botón derecho del mouse la solución recién creada y seleccionamos del menú contextual agregar nuevo proyecto.

imageCuando aparece la opción de seleccionar el tipo de proyecto deseado seleccionamos la opción de class library en el tipo de proyecto Windows bajo C#. Al proyecto le vamos a poner de nombre CapaDeAccesoADatos.

image Después de creada la capa de acceso a datos – al menos el proyecto – procedemos a agregar el modelo del entitiy framework. Debemos recordar, que en el post anterior mencioado al principio de este post, indicabamos que el EF sustituye a la capa de acceso a datos. Por esta razón en este componente de acceso a datos, solamente vamos a tener el modelo generado por el EF; en post posteriores vamos a extender el EF con clases adicionales que se agregarán a esta librería.

Para crear un modelo de entitidades le damos clic y botón derecho al proyecto recién creado y seleccionamos agregar nuevo ítem.

image En el diálogo de seleccionar ítem escojemos la opción ADO.NET Entity Model. Le vamos a llamar UseCasesModel.

image Cuando inicia el “wizard” del EF en el primer paso seleccionamos la opción generar desde base de datos. Seguidamente creamos una nueva conexión a la base de datos que recién acabamos de crear; le decimos además al wizard que agregue el string de conexión al archivo app.config con el nombre UseCasesEntities.

image Seleccionamos Next y procedemos a seleccionar las tablas que vamos a utilizar en nuestro modelo. En este caso, vamos a mapear en el modelo, todas las tablas creadas en el diseño de la base de datos hecha en SQLServer.

image El modelo generado es el siguiente

image Podríamos caer en la tentanción de pensar que lo único que el EF hace es mapear las tablas en clases y ponerlas a nuestra disposición para las tareas tradicionales que llevamos normalmente a cabo en una base de datos tales como el CRUD. Pero si vemos el modelo generado con atención, podemos ver que han sucedido cosas interesantes gracias a la forma en que ser tratan las relaciones entre objetos y entre tablas. Tal vez el cambio que esta más a la vista, es que los campos que manejan las llaves foráneas en la base de datos, fueron sustituidas por objetos de navegación. Esto nos permite una mayor flexibilidad ya que podemos navegar en ambas direcciones en la tabla, y el EF se encarga de administrar las relaciones a nivel de tablas.

En el paso que estamos, la solución debería lucir de la siguiente manera:

image En este momento solo tenemos una librería – dll – que va a convertirse en mi capa de acceso a datos. En el próximo post, vamos a desarrollar la capa de lógica de negocios.

Technorati Tags: ,