24 dic 2010

Unity - Pasar cadenas de conexión al constructor

Actualmente me encuentro desarrollando la arquitectura de un sistema orientado al dominio (Domain Driven Design), bajo C# en Visual Studio 2010, utilizando el nuevo Entity Framework 4. Estoy utilizando Unity como resolvedor e inyectador de dependencias. Ahora bien, como expliqué en posts pasados, utilicé las plantillas T4 para generar mis entidades y mi contexto de conexión. Estaba trabajando instanciando en cada consulta al contexto que me generaba el EF. Cuando hablo de contexto, me refiero a la clase parcial cuyo nombre lo toma en base al nombre que ingresamos cuando hicimos click en [Add Code Generation Item...].
Básicamente borré esa clase e hice que mis repositorios heredaran directamente de ObjectContext. Un ejemplo de una clase repositorio es la siguiente:
  
namespace mtcholakian.samples.TestDDD.Data.Repositories
{
public class CustomerRepository : GenericRepository<Customer>, ICustomerRepository
{
public CustomerRepository(string connectionString)
: base(connectionString)
{
}

}
}


Si observan en el constructor de la clase, estamos esperando una cadena de conexión. Esta cadena la tomo desde el App.Config o archivo de configuración. Ahora bien, el contenedor de Unity es el que me devuelve una instancia de CustomerRepository, pero cómo hago para pasarle ese parámetro de conexión? Fácil, nuestro App.Config tendrá que lucir de la siguiente manera:

  













Aquí se le dice que el valor del connectionString es "SampleDbEntities", lo cual es el nombre del key de la sección connectionString que va a estar declarada dentro del App.Config también.
Ahora, una cosa más y lo más interesante de todo es que tenemos un atributo typeConverter. Lo que nos dice es que al pasarle al constructor el parámetro connectionString lo resuelva esa clase, que tenemos que definir más arriba de la siguiente forma por ejemplo:

  



Y ahora simplemente vemos la definición en sí de la clase:

  
namespace mtcholakian.samples.TestDDD.Utils
{
public class ConnectionStringTypeConverter : TypeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
return ConfigurationManager.ConnectionStrings[value.ToString()].ConnectionString;
}
}
}


Lo que hace es recibir un valor, en nuestro caso será el que definimos en el parámetro param, "SampleDBEntities" y en base a ese string devuelve la entrada de connectionStrings del App.Config que contiene la conexión a la base de datos.
Listo!
Una cosa muy importante es que la declaración de los tipos del unity aplica únicamente a Unity 2.0, no a la versión 1.4, ya que utilizaba un elemento typeConfig del tipo TypeInjectionElement que no viene más a partir de la versión 2.0.
Espero les haya sido útil.
Saludos,

Mike

9 dic 2010

Unity - Inyectar dependencias genéricas

Siguiendo con mis entradas anteriores y con la implementación de mi patrón Repositorio, se me ocurrió inyectar una dependencia en el constructor de una clase.
Unity resuelve en forma automática las dependencias en un constructor, lo cual significa que no tenemos que declarar ese parámetro explícitamente dentro de la sección <types>. En mi caso estoy declarando los mapeos en el archivo de configuración (App.Config), entonces cuando el contenedor detecte esa dependencia en el constructor, automáticamente le inyectará la implementación que hayamos declarado.
Lo interesante es cómo inyectar una dependencia y que esta además sea genérica.
Paso a detallar mi clase en cuestión:
    

public class CustomerRepository : GenericRepository<Customer>, ICustomerRepository
{
//la interfaz genérica es la que el contenedor de Unity debe resolver
public CustomerRepository(IContext<Customer> context) : base(context)
{
}

}


Nuestro archivo de configuración tendrá un aspecto similar al siguiente:


<typeAlias alias="IContext`1" type="mtcholakian.samples.TestDDD.Business.Core.IContext`1,Business.Core"/>
<typeAlias alias="Context`1" type="mtcholakian.samples.TestDDD.Data.Context.Context`1,Data"/>


Observen cómo se declara un generics y luego la clase que lo implementa.
Finalmente dentro de nuestro container declaramos el mapeo:
    
<container name="RootContainer">
<types>
<type type="IContext`1" mapTo="Context`1" name=""></type>
</types>
</container>


Luego, cuando desde la aplicación instanciemos CustomerRepository obtendremos una instancia en el constructor con la clase indicada.
Espero les haya sido útil.
Saludos,
Mike

5 dic 2010

Entity Framework 4 - Cómo obtener un objeto por su primary key

Implementando mi patrón Repository, me encontré con un problema al tratar de hacer un método del estilo GetObjectById(int id), que básicamente devolvería un objeto a partir de su clave primaria en la base de datos.
Por más que revisé toda la web, no encontré la solución, así que luego de estar un largo rato probando voy a plasmar aquí la forma de resolverlo.
Básicamente lo que hago es un método donde le paso un array de objects, ya que la clave primaria en la BD puede estar formada por varios campos, donde cada elemento es una clave.
Aquí el método en cuestión:


public T GetEntityById(params object[] keys)
{
using (SampleDBEntities context = new SampleDBEntities(SampleDBEntities.ConnectionString))
{
EntitySet en = context.CreateObjectSet<T>().EntitySet;
EntityKeyMember[] entityKeys = new EntityKeyMember[en.ElementType.KeyMembers.Count];

for(int i=0;i < en.ElementType.KeyMembers.Count;i++)
{
entityKeys[i] = new EntityKeyMember();
entityKeys[i].Key = en.ElementType.KeyMembers[i].Name;
entityKeys[i].Value = keys[i];
}

EntityKey entityKey = new System.Data.EntityKey { EntityContainerName = en.EntityContainer.Name, EntityKeyValues = entityKeys, EntitySetName = en.Name };
object outObject = null;

context.TryGetObjectByKey(entityKey, out outObject);

return (T)outObject;
}
}



Luego desde un main podrían usarlo de la siguiente forma:


static void Main(string[] args)
{
//aquí uso Unity para resolver implementaciones
ICustomerRepository repo = ProxyGenerator.GetImplementation<ICustomerRepository>("CustomerMappging");

//obtengo el cliente por su primary key

Customer customer = repo.GetCustomerById(1);
}


Espero que haya sido útil.
Saludos,
Mike

28 nov 2010

Inyección de Dependencias con Unity

Voy a iniciar este tema, ya que comenzó a interesarme a raíz de un draft que estoy leyendo de microsoft, sobre arquitecturas orientadas al dominio (Domain Driven Design).
Lo pueden bajar desde aquí.
La idea de inyectar dependencias es un tema muy interesante que nos va a servir en el momento de desacoplar capas y facilitar los procesos de test.
Para armar mi solución me basé en el proyecto del link que transcribo arriba, la cual simpliqué bastante, a modo de poder realizar rápidamente las pruebas que me interesaban.
Mi solución consta de los siguientes proyectos:
  • Business.MainModule. Contiene los servicios, que son el punto de entrada de las aplicaciones ASP .NET MVC, WinForm o RIA y las interfaces de los contratos para los repositorios.
  • Business.MainModule.Entities. Contiene las entidades del dominio. Basándome en mi ejemplo, fueron generadas gracias las plantillas T4 de Entity Framework 4. El tipo de entidades que generé fueron del tipo POCO (Plain CLR Objects). Este tipo de entidades no está ligado a ninguna tecnología en particular, o sea, no tienen referencia a ninguna library específica de modo que queden relacionados a la capa de datos. Prefería este tipo de plantillas a las IPOCO, ya que si bien estas últimas vienen preparas para WCF, me parecieron más complejas de implementar.
  • Data. Es la capa de infraestructura de acceso a Datos. Contiene el modelo .edmx de EF 4 y la clase T4 para generación del contexto. Esta capa implementa los repositorios que definimos en Business.MainModule.
  • Data.Mock. Es mi proyecto de test, donde se ve la potencia de DI, al reemplazar "on the fly" la capa de infraestructura por un "fake", para realizar los test.
  • TestDomainDrivenDesign. Es mi capa de presentación, desde donde realizo las pruebas.
No voy a entrar en detalle, ya que en el pdf que nombré más arriba está más que claro. Mi modelo es más simplificado puesto que no uso proyectos Core en Business o en Data.
Aquí expongo como se vería el proyecto:


Mi idea al probar unity es NO hacer referencia desde la capa de presentación, en este caso, TestDomainDrivenDesign hacia la capa Data, es decir, no instanciar directamente los repositorios, sino que sea el contenedor de Unity el que nos de la instancia.
La idea es la siguiente: cuando te pida la interfaz del tipo "IInterfaz" devolveme "Clase".
Hay varias formas de establecer esta relación, o mejor dicho, este mapeo entre interfaz y clase implementadora, yo opté por la opción de hacer estas definiciones en el App.Config o Web.Config (dependiendo de nuestra capa de presentación).
Primeramente hay que bajarse las dlls de Unity, lo pueden hacer desde aquí.
A su capa de presentación deberan agregar las referencias a: Microsoft.Practices.Unity y Microsoft.Practices.Configuration.
Pasemos a la configuración de nuestro archivo de configuración ejemplo:



























Como podemos ver,hay varias secciones que nos interesan:
  1. Tenemos dentro de configSections una sección llamada "unity". Luego la definiremos más abajo y es la que contendrá la definición de los mapeos. Es más recomendable hacer referencia a un archivo externo que tenga la configuración del unity y no mezclarlo con el que usamos en nuestra aplicación. En este caso, como es una aplicación pequeña opté por tenerlo todo en junto. Pero es algo a tener en cuenta.
  2. Tengo una sección connectionString con la conexión al modelo de Entity Framework 4.
Lo que primero debemos hacer es definir nuestros "alias", que son las clases e interfaces que vamos a usar en el mapeo y en que assemblies están definidas.







Luego, viene la parte donde le decimos que interface se mapea a que clase y algo MUY importante el "name".






Ahora veamos como hacer la llamada al contenedor de unity para que nos devuelva una instancia del repository "real", en este caso, CustomerRepository. El main, junto con las pruebas a realizar se verías más o menos así:

public class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();

var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

section.Configure(container,"RootContainer");

ICustomerRepository repo = container.Resolve<icustomerrepository>("CustomerMappging");

//creates a new customer
Customer customer = new Customer { CustomerCode = "123", CountryId = 1, CompanyName = "Prueba", ContactName = "Miguel", ContactTitle = "Ing" };

//adds a new customer
repo.AddCustomer(customer);

//retrieves all the customers
List<customer> list = (List<customer>)repo.GetAllCustomers();

foreach (Customer c in list)
{
Console.WriteLine("Id: {0}, Name: {1}", c.CustomerId, c.ContactName);
}

}
}

Si nos fijamos nunca hicimos referencias a la clase, siempre contra la interface.
Por ello sería muy válido, y ahora viene la parte interesante y que nos va a ayudar en el momento de las pruebas, que es, reemplazar nuestro repositorio por otro "fake".
Bastará con hacer este simple cambio en el App.Config:














Listo! no tuvimos que cambiar nada NI en la capa de presentación. El contenedor nos devuelve una instancia de CustomerRepositoryMock con nuestra implementación "fake" los métodos de la interfaz.
Por último: para hacer las pruebas en el bin\debug hay que pegar las .dlls del proyecto de Data y Data.Mock, sino el reflection no encontraría las clases que definimos en el App.Config.

Pueden descargar el código completo para Microsoft Visual Studio 2010 desde aquí.
Aquí dejo el script que deberán correr sobre una base de datos para que la aplicación quede 100% funcional.
Saludos,
Mike

21 nov 2010

Gestión de Excepciones - Parte II

  • No manejar errores atrapando excepciones no específicas, como aquellas que heredan de System.Exception. El siguiente es un mal uso:

public class MalManejoExcepciones
{
public void DoWork(){//Hacer algo que dispare una excepción}
}

public void MethodWithBadHandler()
{
try
{
DoWork();
}
catch (Exception e)
{
//Atrapar la excepción y continuar ejecutando
}
}

  • Hay ocasiones en las que no se deben atrapar las excepciones y dejar que la aplicación "explote" y termine.
  • Atrapar las excepciones que sabemos que debemos hacer en cada caso. No atrapar excepciones no específicas y re lanzarlas.
  • Atrapar las excepciones que sabemos que podemos continuar con la ejecución de nuestra aplicación. Por ejemplo: si recibimos una excepción del tipo "FileNotFoundException", se puede atrapar y permitirle al usuario que especifique un archivo diferente. En cambio si se recibe un error desconocido y no sabemos si es seguro que la aplicación en ese estado continúe no se debe atrapar la excepción.
  • Usar el bloque try-finally preferentemente al try-catch. El bloque catch permite atrapar excepciones, mientras que el finally liberar recursos.
  • Disparar únicamente utilizando la palabra "throw", de esta manera preservamos el call stack trace. Ejemplo:


public void DoWork(Object anObject)
{
// Do some work that might throw exceptions.
if (anObject == null)
{
throw new ArgumentNullException("anObject","Specify a non-null argument.");
}
// Do work with o.
}

public void MethodWithBadCatch(Object anObject)
{
try
{
DoWork(anObject);
}
catch(ArgumentNullException e)
{
System.Diagnostics.Debug.Write(e.Message);
// Incorrecto
throw e;
// Debería ser:
// throw;
}
}

Gestión de Excepciones - Parte I

En este artículo voy a explicas unas guías para tener en cuenta al momento de trabajar con excepciones.

Las excepciones son el mecanismo estándar para reportar errorres. Las aplicaciones y librerías no deberían usar códigos de errores para devolver errores. Además permite disparar errores desde miembros como constructores que no tienen un tipo de datos de retorno.

Guías para disparar excepciones
Las excepciones se disparan cuando un miembro no puede hacer con éxito aquello para lo cual fue diseñado. Por ejemplo
si tengo que conectarme a un end point de WCF y el mismo no responde, disparo una excepción.
A tener en cuenta:

  • No devolver códigos de error. Las excepciones son el medio primario para reportar errores.
  • No usar excepciones para controlar el flujo normal de la aplicación. Siempre que se pueda tratar de no pensaren programar para disparar excepciones. Si se pueden evitar, mejor. Ejemplo:


public class Disparo
{
public static void ShowMessage(string mensaje)
{
if(mensaje == null)
{
throw new ArgumentNullException("mensaje");
}
}

}

public class Testeo
{
public static void Procesar(List<string> mensajes)
{
foreach(string mensaje in mensajes)
{
if(mensaje !=null)
{
Disparo.ShowMessage(mensaje);
}
}
}
}


  • Tener en cuenta el gasto de performance que implica disparar excepciones.
  • No usar miembros públicos que disparen una excepción basado en un código de error. Ejemplo: void ParseoString(string value, bool dispararExcepcion);
  • Usar métodos helpers de construcción de excepciones ya que la misma excepción puede dispararse de diferentes lugares. Pero ojo, estos helpers no deben disparar la excepción, solo inicializar propiedades, sino alteraríamos el stack trace.
  • No disparar excepciones desde la cláusula finally.

17 oct 2010

IIS 7 y las delegaciones - Parte II

En la entrega anterior había explicado cómo solucionar un error relacionado con la autenticación.
Ahora veremos una nueva cuestión relacionada con la autorización.
Hosteando un sitio web VS2010 en IIS 7 me producía el siguiente error:

El error acusa que "falta definir una sección". Pero...dónde? Veamos el esquema general de archivos de configuración en el IIS7.



En la imágen anterior se ve claramente el rol que juegan los diferentes archivos de configuración, por un lado tenemos los del framework (web.config y machine.config) y por otro lado los del server (applicationHost.config). Entre los 3 se "mezclan" o bien dicho de otra forma, se toman las características que herederá nuestra web.config a nivel de aplicación (imágen resultante de la derecha). Los tags del framework estarán dentro de la sección <system.web> mientras que los del server dentro de <system.webServer>. Como siempre recomiendo visitar la web del IIS7.
Bueno, ahora volvamos al error en cuestión.
El mismo nos dice que hay una entrada "faltante" dentro de <system.webServer>, como bien observamos en el esquema se trata de una configuración del servidor. Seguimos estos pasos:
  1. Abrir el archivo applicationHost.config (%windir%\inetsrv\config).
  2. Ubicar la entrada en cuestion y la subentrada <sectionGroup name="security">
  3. Agregamos la siguiente línea:

    <section name="authorization" overrideModeDefault="Allow" />


  4. Y se le indica, tal como vimos en la entrega anterior, el atributo overrideModeDefault en "Allow", para que nuestro Web.Config lo pueda pisar.
  5. Grabamos el archivo.
  6. Abrimos el archivo Web.Config de nuestra aplicación y agregamos estas líneas:

    <security>
    <authorization>
    <add users="*" accesType="Allow"/>
    </authorization>
    </security>
  7. En este caso no restringimos el acceso a algún usuario o rol en particular.
  8. Corremos la aplicación nuevamente.
Espero les haya sido útil.
Saludos,
Mike

16 oct 2010

IIS 7 y las delegaciones - Parte I

Voy a iniciar este tema motivado por las pruebas que estoy realizando con VS2010 y en particular la publicación de un servicio WCF. El problema radicaba en el momento de la publicación del mismo, hosteado en IIS 7. Al momento de acceder al mismo de la siguiente forma:

http://localhost/wcf/cryptohashservice/service.svc

Me aparecía un mensaje de error similar al siguiente:

Y aquí comienza el tema de la entrada: Delegaciones en IIS 7.
No voy a ser extenso con el tema ni muchos menos, ya que en el sitio oficinal del IIS encontrarán excelente documentación al respecto. Voy a ir directo al grano, lo que implica entender qué está pasando y darle solución a nuestro error.
Lo que nos dice el browser es que hay otro archivo que nos está definiendo un "nivel de lockeo". El archivo en cuestion es: applicationHost.config. Lo pueden encontrar en %windir%\System32\inetsrv\config. (Es importante que cuando editemos este archivo lo hagamos con permiso de administrador).
Lo que tenemos que hacer ahora es lo siguiente:
  1. Abrimos el archivo web.config de nuestra aplicación.
  2. Dentro de la sección <system.webserver> (que está dentro de <configuration> )
    agregamos lo siguiente

    <security>
    <authentication>
    <anonymousAuthentication enabled="true" userName="/>
    </authentication>
    </security>


    Lo único que hicimos fue establecer el modo "anónimo" de autenticación.
  3. Ahora, lo que debemos hacer es permitir que se pueda "pisar" esta configuración, y debemos hacerlo a un nivel superior, y aquí entra en acción nuestro archivo applicationHost.config.
  4. Nos paramos al final de archivo, justo antes del cierre del tag y agregamos lo siguiente:


    <location path="WCF" overrrideMode="Allow">
    <system.WebServer>
    <security>
    <authentication>
    <anonymousAuthentication />
    </authentication>
    </security>
    </system.WebServer>
    </location>


    Si observamos no es más que un simple tag con un atributo overrideMode en "Allow", con esto decimos que cualquier archivo de configuración que esté en un nivel inferior (ya veremos luego como se consideran estos niveles al correr una aplicación) pueda pisar esta configuración.
  5. Además observemos que el tag tiene un atributo path, este es el path de la aplicación hosteada en el IIS7.
  6. Lo único que nos queda es tratar de browsear nuevamente el servicio.


    Espero que les haya sido útil.
Saludos,
Milke

30 sept 2010

IEnumerable<T> a DataTable

Aquí presento una función que recibe un IEnumerable<T> como parámetro, el cual podría ser un lista genérica y la transforma en un DataTable, devolviendo como columnas las propiedades del tipo T . OJO: esta técnica aplica únicamente a properites, no así miembros públicos fields, y no soporta miembros nulleables. En una futura entrega voy a presentar una función más completa.


public static DataTable ListToDataTable<T>(IEnumerable<T> list)
{
DataTable dt = new DataTable();
List<PropertyInfo> properties = new List<PropertyInfo>();

foreach (PropertyInfo propInfo in typeof(T).GetProperties())
{
//cada propiedad va a ser una nueva columna del DataTable
properties.Add(propInfo);

DataColumn col = new DataColumn(propInfo.Name, propInfo.PropertyType);

dt.Columns.Add(col);
}

foreach (T item in list)
{
DataRow row = dt.NewRow();

foreach (PropertyInfo prop in properties)
{
row[prop.Name] = prop.GetValue(item, null);
}

dt.Rows.Add(row);
}

return dt;
}

Saludos,
Mike

Max de un IEnumerable<T>

Voy a explicar como aplicar una típica función agregada de SQL: Max, sobre un IEnumerable<T>, a partir de un campo de ese T que van a tener todos los tipos que puedan mapearse contra ese tipo T.

Hay dos formas de aplicarlo.


1) Forma más explicativa:


public int GetMaxId<T>(IEnumerable<T> listx, string campo)
{
//Aquí mediante reflection obtenemos el valor de la propiedad cuyo nombre nos llega por parámetro
Expression> exp = o => Convert.ToInt32(typeof(T).GetProperty(campo).GetValue(o, null));

//Luego agregamos el tipo de datos y la propiedad del T que nos interesa tomar en cuenta
var list = Expression.Parameter(typeof(IEnumerable), campo);

//Luego construimos la expresión del Max en sí misma, notar que en lugar de Max podría ir otra función SQL
MethodCallExpression maxExp = Expression.Call(typeof(Enumerable), "Max"
new Type[] { typeof(T), exp.Body.Type }, list, exp);

//Por último generamos la expresión lambda
var lambda = Expression.Lambda , int>>(maxExp, list);

//y la ejecutamos, obteniendo el max de la propiedad "campo" de listx.
var result = lambda.Compile()(listx);
}

Luego para probarlo bastaría con hacer lo siguiente:

......
...

static void Main()
{
List<Cliente> listClients = new List<Cliente>();
listClients.Add(new Cliente { Edad = 20 });
listClients.Add(new Cliente { Edad = 22 });
listClients.Add(new Cliente { Edad = 24 });

int max = GetMaxId<Cliente>(listClients, "Edad");

}

......
...

class Cliente
{
public int Edad { get; set; }
}


2) Luego la forma más simple que se reduce a una línea de código es la siguiente:

public int GetMaxId<T>(IEnumerable<T> listx, string campo)
{
return listx.Max(o => Convert.ToInt32(typeof(T).GetProperty(campo).GetValue(o, null));
}


Saludos,
Mike