EntityFramework con repositorios genéricos

computer-1185626_1280
EntityFramework es una herramienta que le permite a los programadores tener una capa más de abstracción entre su aplicación y su base de datos. Con EntityFramework podemos crear tablas ligadas a nuestras clases, y con ello viene la ventaja de poder ir versionando nuestra base de datos. Pero EntityFramework no es el único ORM en el mercado, existen otros entre Dapper, Massive y PetaPoco.

Entre todas las opciones existentes de ORM y de diferentes gestores de bases de datos, viene siendo aún más importante ir creando una capa entre la lógica de la aplicación y la base de datos. Para ello, los programadores suelen utilizar el patrón de repositorios genéricos, con unas cuantas funciones. Estas se mantienen igual, y lo que cambian son sus implementaciones.

Con .NET Core, la situación se vuelve más sencilla, ya que permite “inyectar” el repositorio encargado. La clase (o un controlador) desconoce quien la implementa, simplemente la usa. La forma de implementación no es de su incumbencia y al menos así podemos evitar la cohesión entre clases, que a la larga provocan problemas.

Como se puede observar en el código siguiente, existe una variable llamada “repository”, este se encarga de agregar la entidad/registro en la base de datos. La función Index (que es una acción de un controlador) no conoce ni quién, ni cómo la implementa, simplemente la usa. ¿El beneficio? en cualquier momento podemos cambiar de SqlServer a MySQL o MongoDb, sin necesidad de mover esa función.

Prerequisitos

Este artículo asume que se está usando Visual Studio 2015. Para poder continuar, se requiere de igual forma, modificar el archivo project.json (archivo del proyecto) para incluir los siguientes paquetes.

  • “Jaguar.DataAccess.EntityFramework” es un paquete que contiene el repositorio genérico, es una versión estable, pero que se entrega sin responsabilidad alguna de parte del autor, su código fuente estará pronto en Github.
  • “Microsoft.EntityFrameworkCore.SqlServer” es el paquete que permite conectarse especificamente a SQL Server. Este puede cambiarse de acuerdo a la página oficial.
  • “Microsoft.EntityframeworkCore.Tools” nos permite ir actualizando la base de datos conforme vamos haciendo los cambios.

Crear un modelo

En un ORM, cada modelo es una clase que esta enlazada a una tabla en la base de datos. De tal forma que el programador simplemente crea la clase y -en este caso- EntityFramework se encarga de realizar el resto.

Para el repositorio genérico, cada una de las clases deben implementar una interfaz. De tal manera que todas compartan al menos los requeridos para el repositorio. Esa interfaz en este caso es la de Jaguar.DataAccess.IEntity.

Cada clase debe tener al menos un campo clave que lo identifique. De manera predeterminada los campos llamados Id, o CustomerId son considerados automáticamente “campos claves”. IEntity, utiliza un campo tipo Guid.

Crear un contexto de EntityFramework

Para que EntityFramework pueda identificar que clases creará en la base de datos, estas se deben de poner en un “contexto”, para ello se requiere de crear una clase como la siguiente:

Solía suceder que EntityFramework utilizaba el nombre de la clase para compararlo en el webconfig en busca de una cadena de conexión, sin embargo en este caso (EntityFrameworkCore) las cosas ya no son así.

Es por eso que en la clase se crean como minímo 3 funciones, las primeras dos son constructores y la última es la que configura la cadena de conexión.

En el caso de los constructores, uno es utilizado por el repositorio para obtener la configuración recibida por el DI (inyección de dependencias) de .NET. El segudo, para los comandos de migración que se explica más adelante.

La última propiedad, es la interesante, básicamente ahí decimos que se creará una tabla de “Customer”.

Configurar DI

La inyección de dependencias es algo muy útil, y en este caso la usaremos en el archivo Startup.cs para poder crear la relación con el repositorio.

En este punto, existe una extensión que permite configurar ese contexto, para que sirva como el repositorio. A ese repositorio se le debe pasar la cadena de conexión, así que para ello, se debe configurar el archivo “appsettings.json”.

La base de datos que se usa en la cadena de conexión ha sido creada previamente, y asignado los permisos requeridos al usuario.

Creando las tablas (migración)

Con EntityFrameworkCore, los comandos cambiaron. Entre los paquetes que se instalaron en el proyecto se encuentra “Microsoft.EntityframeworkCore.Tools”, el cual es el encargado de crear los comandos necesarios para las migraciones.

Primero se debe generar las rutinas que se cargaran a la base de datos, corra los siguientes comandos para crear las tablas.

cd "srcmiapp"
dotnet ef migrations add inicial
dotnet ef database update

Al finalizar, las tablas fueron creadas en la base de datos. Considere correr esos comandos en el directorio principal de la aplicación donde esta el archivo “project.json”.

Haciendo uso del repositorio genérico

La inyección de dependencias (DI) es un concepto sencillo de comprender. El programador elabora un contrato, que tiene ciertas claúsulas. Todas esas cláusulas son obligatorias, de tal manera que al “contratar” a alguién, este debe de cumplir con dichas cláusulas. El contrato es una interfaz, que contiene las funciones que se ejecutará, pero no la implementación.

De tal manera, que en el paso anterior se especificó a .NET que el encargado del repositorio será la clase DataContext. Esta clase es la que ya se hizo anteriormente, es posible que al observar se de cuenta que la clase extienda la clase “Jaguar.DataAccess.EntityFramework.RepositoryContext” al mismo tiempo implementa la interfaz IRepository.

Con ello, .NET es capaz de inyectar en el constructor de la clase (HomeController), una instancia de DataContext con los métodos que tiene la interfaz IRepository.

Como se puede observar en el código anterior, existe un controlador que recibe el repositorio. Este lo asigna a una variable para que pueda ser usada dentro de ese ámbito. En la función Index, se agrega un cliente, usando la función AddEntity.

La interfaz Jaguar.DataAccess.IRepository contiene la lista de todas las funciones.

Recomendaciones

En conclusión, EntityFrameworkCore viene mejorando mucho en rendimiento y compatibilidad con diferentes proveedores. Utilizar un patrón de repositorio genéricos se vuelve aún más importante. Independientemente si se utiliza el repositorio genérico descrito aquí, así como cualquier otro, es importante adquirir la práctica de hacerlo bajo ese patrón.

Usando dotnet para páginas .NET en linux

Un pingüino feliz.
Correr en Linux una aplicación hecha en .NET Core ahora es muy sencillo usando unos comandos con dotnet.

La versión actual es .NET Core 1.0.1 (1.0.2 únicamente en macOS) y la documentación oficial menciona que podemos correr una aplicación web en Ubuntu. Ubuntu es una distribución de linux muy popular, la última versión es la 16.04, aunque dotnet se puede instalar en la versión 14.

Es importante mencionar que los comandos que se exponen en este artículo no consideran que quien los ejecute se encuentre detrás de un proxy. En ese caso, el ambiente debe ser configurado para que las variables de entorno “http_proxy” y “https_proxy” se encuentren configuradas de manera global al igual que configurar apt. Apt, podría no funcionar bien y en ese caso deberían configurar la opción No-Cache. De igual forma, algunas de las herramientas adicionales como “npm” y “bower” deben estar configuradas correctamente.

Instalar dotnet

.NET Core se descarga desde un repositorio , así que hay que registrarlo para poder descargar desde ahí.

La rutina crea un archivo “/etc/apt/sources.list.d/dotnetdev.list” este sirve como el canal para descargar los archivos requeridos para la instalación. Se debe considerar que “xenial” es para Ubuntu 16 y “trusty” para Ubuntu 14.

A diferencia de la versión oficial, estamos usando keyserver.ubuntu.com para descargar la llave del repositorio, esto solamente será necesario si tenemos problemas con la documentación oficial.

Crear una aplicación .NET Core

Una aplicación desarrollada con .NET Core puede correr sin problemas independientemente de la plataforma. Si un programador sigue la documentación oficial  podrá crear un directorio y correr unos comandos para poner en funcionamiento una aplicación, sin embargo existen herramientas como Yeoman.

Yeoman es representado por un sujeto con herramientas en la mano.

Yeoman es una herramienta que permite inicializar una aplicación web (entre otras) de manera sencilla. Utiliza una arquitectura modular, de tal manera que podemos instalar varios “generadores” que se encargarán de llenar las plantillas.

Yeoman, el generador

Con Yeoman instalado, basta con abrir una consola y correr el comando “yo aspnet”. Al ejecutarse, un menú aparece en pantalla, en el cuál se puede seleccionar el tipo de aplicación que deseamos crear. El programador puede seleccionar “Web Application Basic (without Membership and Authorization)”, eso creará una simple aplicación, pero no está limitada a ello, por lo cuál se puede elegir cualquier otra.

Seleccionando el tipo de aplicación.

Una vez que se ha seleccionado el tipo de aplicación, Yeoman nos preguntará que tipo de “framework UI” queremos usar, entre los cuales se puede elegir entre:

Seleccionando el framework UI.

Una vez elegido el tipo de diseño deseado, se procede a ponerle un nombre a la aplicación. Ese nombre será el nombre de la carpeta que se creará en el directorio donde esté corriendo Yeoman.

Eligiendo el nombre.

Corriendo la aplicación

Una aplicación desarrollada en .NET Core, debe restaurarse primero para poder ser ejecutada. Para ello, dotnet cuenta con el comando “restore”, que permite que la aplicación descargue lo necesario para que corra sin problemas.

Ejecutando el comando dotnet restore

Una vez que la aplicación ha sido restaurada, es cuando puede ser ejecutada por medio del comando “run”

cd miapp
sudo dotnet run --urls http://*:80;

Ejecutando el comando dotnet run --urls

Cuando la aplicación se encuentra corriendo, esta puede ser visualizada por cualquier navegador.

Una página web en el navegador.

Recomendaciones

.NET Core viene con muchas mejoras y aunque aún le queda camino por recorrer, se puede decir que va por buen camino. En la aplicación de ejemplo se uso el modificador “–urls”, esto para permitir que se vea la página en el puerto 80, ya que de manera predeterminada corre en “http://localhost:5000”.

Registrar eventos con NLog usando C#

Usando nlog en una libreta.

Una de las tareas a la que un programador suele dar menos atención es al registro de eventos de una aplicación. Es importante durante el desarrollo y aún más cuando la aplicación se encuentra en productivo realizar esa tarea. NLog puede hacer esa tarea sin problemas.

Un registro o bitácora nos permite ir guardando información de nuestro programa con la finalidad de que posteriormente podamos encontrar la causa de un problema o la ausencia del mismo. La utilidad de estas herramientas es muy importante porque nos ahorrará mucho tiempo durante todas las etapas de un proyecto que al final es importante.

Implementación

En .NET Core se vuelve múy fácil la implementación de cualquiera de esas herramientas ya que prácticamente sólo debemos configurarlas en un sólo lugar, haciendo que las demás clases no necesiten saber quién ni cómo se hace el registro y que posteriormente en caso de ser necesario, pueda cambiar de manera rápida la herramienta.

Ahora bien, partiendo de la idea de que casi todo es manejado por paquetes, vamos a instalar el paquete correspondiente “Nlog” y el “NLog.Extensions.Logging“, que para el momento en que se escribe este artículo, aún se encuentran en etapa de prueba, es por eso que demos usar el modificador -“Pre” lo cuál instalará el paquete aún no siendo la versión final.

> Install-Package Nlog -Pre
> Install-Package NLog.Extensions.Logging -Pre

Una vez que los paquetes se instalan en el proyecto, lo siguiente es definir la configuración de la herramienta, esto suele cambiar de acuerdo a la herramienta que usemos. Algunos como Serilog usan ya el archivo “project.json”, otros como log4net siguen usando archivos “*.config”, pero en todos hay que definir básicamente una cosa: a dónde enviaremos la información.

En el caso de Nlog, lo que debemos hacer es crear un archivo llamado nlog.config (en raíz del proyecto).

.NET Core utiliza un inyector de dependencias integrado, lo que significa que los programadores pueden incluir casi cualquier clase que pueda realizar la tarea sin conocer quién la implementa.

Para usar esa característica, debemos ir al archivo “Startup.cs”, esa clase es ejecutada justo antes de iniciar la aplicación, de tal manera que es un buen lugar para ir registrando quiénes van a realizar diferentes tareas. Una de ellas: el registro de eventos.

NLog contiene una extensión de ILoggerFactory que permite crear la función “AddNlog()”, e implementar en .NET Core lo necesario para poder usarlo.

El registro de eventos.

Durante el desarrollo de la aplicación, es importante ir registrando los eventos que ocurran.

Una vez que el proyecto se ejecuta el registro se va guardando, dando como resultado un archivo de texto con la información que generada. Inclusive si no hemos configurado la herramienta, la clase podrá funcionar sin problemas. Por lo tanto es una buena recomendación incluir en el constructor al quien se encargará de los eventos.

Tipo de eventos

La interfaz define varios tipos de eventos, esto es importante porque en producción no querrás ver todos los eventos siendo recomendable ver los que sean advertencias o errores. La tabla de eventos en orden de prioridad es la siguiente:

LogLevel
Trace LogTrace(“Versión 1.0.0-beta.”);
Debug LogDebug(“El registro ha sido guardado.”);
Information LogInformation(“El espacio en disco es óptimo.”);
Warning LogWarning(“Queda poco espacio.”);
Error LogError(“No se pudo guardar el registro porque no esta disponible.”);
Critical LogTrace(“La aplicación no puede continuar.”);

Recomendaciones

Guardar el registro de eventos en una aplicación puede ser en un archivo de texto, XML, un correo así cómo un servicio web. La mayoría de esto depende mucho de la biblioteca que estamos usando. Tómese un momento en leer el listado de destinos de NLog, ahí encontrará ejemplos sobre los demás destinos.

Si decide usar un archivo de texto, procure ubicarlo en una carpeta distinta a la de la aplicación y que tenga los permisos de escritura. De igual manera puede guardar el registro en varias destinos al mismo tiempo. Si decide cambiar de herramienta, con la inyección de dependencias, sólamente deberá cambiar el archivo “Startup.cs” con su nueva configuración. Puede ahorrar mucho tiempo mientras que en otro caso habría que ir archivo por archivo y casi función por función.

Como puede observar, tanto NLog como cualquier otra herramienta nos puede servir para ir registrando eventos. Es muy probable que la herramienta pronto cambie a una versión en productivo. En ese caso ya no será necesario incluir el modificador “-Pre” al instalar el paquete.