domingo, 24 de agosto de 2014

[Patrones] Implementando patrón repositorio - Repository pattern en C# Parte III

En el artículo anterior creamos la estructura para nuestros repositorios y creamos el repositorio para acceso a la base de datos en Sql Server a través de Entity Framework Code First, ahora observaremos como crear los repositorios para acceder a los artículos almacenados en MongoDB y también para obtener los datos de contacto de los empleados que nos proveerá una API en Asp.Net Web Api.

Para iniciar veamos cómo quedará la estructura de nuestro repositorio de MongoDB para cuando lo hayamos terminado:


Como podemos ver tiene la misma estructura que nuestro repositorio de Sql Server del artículo anterior, a diferencia que en este repo utilizamos la entidad Articulo podría ser Empleado, DatosContacto o cualquier otra y también tenemos un repositorio base, el cual nos ayudara a realizar operaciones comunes con la base de datos de Mongo, como por ejemplo, conectarse al servidor, obtener la base de datos, obtener una colección en específico y hacer operaciones sobre esta colección, si quieres ver una introducción sobre MongoDB te invito a que leas este artículo que tengo al respecto.

Ahora observemos el código de nuestro repositorio base para MongoDB

    public class BaseRepository<T> where T : class
    {
        private readonly string _nombreColeccion;
        private MongoDatabase database;
 
        public BaseRepository(string nombreColeccion)
        {
            _nombreColeccion = nombreColeccion;
        }
 
        public void ConectarDb()
        {
            const string connectionString = "mongodb://localhost";
            var client = new MongoClient(connectionString);
            MongoServer server = client.GetServer();
            database = server.GetDatabase("RepositoryPatternDemo");
        }
 
        public void Insertar(T entidad)
        {
            var coleccion = database.GetCollection<T>(_nombreColeccion);
            coleccion.Insert(entidad);
        }
 
        public IQueryable<T> ObtenerTodos()
        {
            var coleccion = database.GetCollection<T>(_nombreColeccion);
            return coleccion.FindAll().AsQueryable();
        }
    }

Nuestro repo base nos permite conectarnos a una base de datos MongoDB  usando el string de conexión y base de datos que vemos en el código esto debería estar en un archivo de configuración, pero para este ejemplo no tiene mucha importancia adicional nos permite insertar un nuevo documento en cualquier colección y nos permite obtener todos los documentos de la base de datos. Es un repositorio base bastante simple al cual le podríamos agregar muchas más operaciones.

Ahora veamos la entidad Artículo la cual se almacena directamente en MongoDB como un documento de tipo Json:

    public class Articulo
    {
        public ObjectId Id { getset; }
 
        public string Titulo { getset; }
 
        public string ContenidoHtml { getset; }
 
        public List<string> Etiquetas { getset; }
 
        public string IdEmpleado { getset; }
    }

Como podemos ver tenemos una propiedad de tipo ObjectId, el cual se generará al guardar el documento en MongoDB, recordemos que todos los documentos en Mongo deben tener este ObjectId por lo tanto aquí lo tenemos en esta entidad y recordemos también que esta entidad será mapeado por Automapper a nuestra entidad de dominio Articulo que es la que en realidad van a conocer los clientes que usen este repositorio.

Y para finalizar con el repositorio de MongoDB observemos el repo específico:

    public class ArticuloRepository : BaseRepository<Articulo>IArticuloRepository
    {
        public ArticuloRepository(string nombreColeccion = "Articulos")
            : base(nombreColeccion)
        {
        }
 
        public List<Dominio.Articulo> ObtenerArticulos()
        {
            AutoMapper.Mapper.CreateMap<Articulo, Dominio.Articulo>();
 
            ConectarDb();
            return new List<Dominio.Articulo>(ObtenerTodos().Select(c =>
                AutoMapper.Mapper.Map<Dominio.Articulo>(c)
                ));
        }
 
        public void GuardarArticulo(Dominio.Articulo articulo)
        {
            AutoMapper.Mapper.CreateMap<Dominio.ArticuloArticulo>();
            var art = AutoMapper.Mapper.Map<Articulo>(articulo);
 
            ConectarDb();
            Insertar(art);
        }
    }

Como podemos observar es un repo bastante sencillo con tan solo dos operaciones, podríamos implementar las que fueran necesarias, y podemos ver que se trabaja de igual forma que el repo de Sql Server del artículo anterior usando automapper para mapear la entidad usada por el repo a la entidad de dominio en este caso la entidad de dominio Articulo.

Y para finalizar el artículo implementaremos el último repositorio del ejemplo, el cual nos permite obtener los datos de contacto de un empleado a través de un servicio Asp.net Web Api. Si quieres obtener más información acerca de Web Api, te invito a visitar el blog de mi amigo y Crack Hernan Guzman.

En este repo usaremos directamente la entidad de dominio DatosContacto, por lo que no necesitaremos del uso de automapper, y tendremos como siempre un repositorio base el cual encapsulará la conexión a nuestra Api y tendremos un repo específico que heredará del repo base. Ahora veamos como es el código del repositorio base:

    public class BaseRepository<T> where T : class 
    {
        public string UrlApi { getset; }
 
        public T ObtenerPorId(string id)
        {
            var client = new HttpClient { BaseAddress = new Uri("http://localhost:38417/") };
 
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
 
            HttpResponseMessage response = client.GetAsync(string.Format("api/DatosContacto/{0}", id)).Result;
 
            if (response.IsSuccessStatusCode)
            {
                var datosContacto = response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<T>(datosContacto.Result);
            }
            else
            {
                return null;
            }
        }
    }

Nuestro repositorio base se encarga de consumir el servicio Web Api, enviando el id del empleado para obtener en formato Json su información de contacto, posteriormente deserializa los datos de contacto en la entidad de dominio DatosContacto y la retorna. (El código de ejemplo del Api lo puedes encontrar en el repositorio en GitHub correspondiente a esta serie de artículos).

Ahora para finalizar observemos como es el código de nuestro repositorio específico para DatosContacto:

    public class DatosContactoRepository : BaseRepository<Dominio.DatosContacto>IDatosContactoRepository
    {
        public Dominio.DatosContacto ObtenerDatosContactoEmpleado(string idEmpleado)
        {
            return ObtenerPorId(idEmpleado);
        }
    }

Es bastante simple, dado que solo tiene una operación.

Y bueno eso es todo por este artículo, en el cual implementamos los repositorios para acceso a MongoDB y para acceso a Web Api, en el próximo artículo terminaremos esta pequeña serie sobre el patrón repositorio o repositoy pattern observando como consumir los repositorios que hemos creado desde algún cliente, como por ejemplo una aplicación Asp.Net Mvc. Espero sea de utilidad y de interés para ustedes.

Continua en: Implementando patrón repositorio - Repository pattern en C# Parte IV

Este ejemplo lo puedes descargar de mi repositorio en GitHub

No olvides visitar mi página en Facebook para mantenerte actualizado de lo que pasa en el Tavo.Net https://www.facebook.com/eltavo.net
Saludos, y buena suerte!

3 comentarios:

  1. Hola. Este codigo me sirve para conectarme a una base de datos MySql? es decir solo tendría que reemplazar la cadena de conexión?

    ResponderEliminar
    Respuestas
    1. Hola beto, creo que este artículo de la serie aplica más para lo que necesitas, dado que se muestra una implementación con EF para SqlServer:

      http://www.eltavo.net/2014/08/patrones-implementando-patron_13.html

      Puedes usar EF pero lo haces con MySql, eso sería lo único que deberías cambiar, lo otro aplica igual, puedes ver este vídeo tutorial de JuanK Ruiz, dónde explica como usar EF con MySql.

      https://juank.io/entity-framework-mysql-sqlserver-csharp/

      Saludos.

      Eliminar
  2. Bueno pienso que todo super, salvo el uso de Entity Framework. Pienso que muchos FrameWork ya implementan en su estructura Repositoty(Linq en equipo con Entity Frameworkk ya proveen las alternativas suficientes para orquestar de forma correcta los accesos a datos separando de forma correcta la lógica de negocio, crear una capa adicional que implementa Repository me resulta un poco Redundante).

    ResponderEliminar