Está en la página 1de 9

Patrón Repositorio (Repository Pattern) y Unidad de

Trabajo (Unit Of Work) en ASP.NET Core WebApi 3.0


Una aplicación de software típica naturalmente necesitará acceder a algún tipo de
almacén de datos para llevar a cabo operaciones CRUD (Crear, Leer, Actualizar,
Eliminar) en los datos, por lo general esto podría ser algún tipo de base de datos,
sistema de archivos o cualquier tipo de mecanismo de almacenamiento utilizado
para persistir de información.
En algunos casos guardar o crear datos puede requerir persistencia en archivos
nuevos o crear una nueva fila en una tabla de una base de datos, en otros casos
guardar datos nuevos puede requerir varias interacciones con varios servicios
basados en la web o aplicaciones y otros servicios que no son generalmente
gestionados por nosotros mismos.
ara ambos casos podemos hacer uso del patrón repositorio (Repository Pattern) y
una unidad de trabajo (Unit Of Work), pero, ¿qué es el patrón repositorio?
El patrón repositorio consiste en separar la lógica que recupera los datos y los
asigna a un modelo de entidad de la lógica de negocios que actúa sobre el modelo,
esto permite que la lógica de negocios sea independiente del tipo de dato que
comprende la capa de origen de datos, en pocas palabras un repositorio media
entre el dominio y las capas de mapeo de datos, actuando como una colección de
objetos de dominio en memoria (M. Fowler), ahora bien, ¿qué es el patrón unidad
de trabajo?
Este centraliza las conexiones a la base de datos realizando un seguimiento de todo
lo que sucede durante una transacción cuando se usan capas de datos y revertirá la
transacción si Commit() no se ha invocado o existen incongruencias lógicas.
Para este ejemplo utilizaremos un repositorio genérico y una unidad de trabajo
aplicándolo al proyecto de Albumes y Artistas que contiene una base de datos en
memoria de sql server. Este proyecto lo he utilizado en post anteriores, he realizado
algunas adaptaciones al código del repositorio que me parecen geniales agregando
programación asíncrona, separando servicios, desacoplando componentes para
lograr una mejor infraestructura dentro del proyecto y que puedan utilizarla en sus
proyectos.
Vamos a crear un proyecto con una solución en blanco en Visual Studio 2019
Preview, luego crearemos 3 carpetas de soluciones y dentro cada carpeta
agregaremos un proyecto que hace referencia a las capas WebApi que contendrá el
manejo de Controllers para exponer o almacenar datos, Entities que hace
referencia a los modelos, en un escenario más sencillo los modelos los crearíamos
en el proyecto WebApi pero recuerda que buscamos desacoplar componentes, la
tercer capa llamada DataAccess que se encargará de acceder a la información de
la base de datos mediante un repositorio genérico y afectar la base de datos
mediante una unidad de trabajo. Los proyectos Entities y DataAccess son
bibliotecas de clases .NET Standard. La organización del proyecto quedaría de la
siguiente manera:

En el proyecto DataAccess crearemos las Clases que implementan las Interfaces


del repositorio genérico y la unidad de trabajo, seguidamente haremos uso de
inyección de dependencias de ambos, si no sabes que es inyección de
dependencias revisa mi post anterior acerca de Inyección de dependencias en. NET
Core.
Creamos la unidad de trabajo, su respectiva Interface y Clase.
UnitOfWork utiliza el contexto de datos que pertenece a la capa de Entities, no
olvidar hacer referencia a dicho proyecto.

Luego crearemos el repositorio genérico.


Puedes notar que tradicionalmente se inyecta una propiedad de contexto de datos
en el constructor del repositorio, pero para esta implementación inyectamos una
propiedad de tipo IUnitOfWork, esto para lograr centralizar las operaciones a la
base de datos.
Nos centraremos en las opciones leer y crear, sobrecargamos el método GetAsync
para poder agregar una condición, ordenar por algún atributo propio del modelo y
agregar relaciones con otros modelos mediante alguna propiedad de navegación.
Ahora vamos a agregar la dependencia en el contenedor de control de inversión
IoC, está clase se crea en una carpeta llamada Middleware, este nombre es
arbitrario y debe estar situada en el proyecto WebApi.

Seguidamente utilizamos el contenedor de inversión de control para inyectar el


servicio en la clase Startup método ConfigureServices en el proyecto WebApi.

Ahora vamos a utilizar el repositorio genérico y la unidad de trabajo en nuestro


Controller, debemos inyectar la interface IGenericRepository pero debemos darle
un tipo y en este caso debe ser tipo Album, inyectamos la interface de unidad de
trabajo IUnitOfWork, después asignamos la inicialización que el IoC se encargó de
instanciar en el inicio y seguidamente podemos proceder a utilizar alguno de los
métodos del repositorio, en este caso el método GetAsync del repositorio en el
método Api Get, nótese que estamos pasando 3 parámetros: parámetro 1 una
condición, parámetro 2 ordenar por algún atributo propio del modelo y parámetro 3
la relación con otro modelo en este caso Artista. Para el caso del método Api Create
utilizamos el método del repositorio CreateAsync el cuál recibe un modelo
serializado en formato json a través del verbo HTTP Post.

Finalmente vamos a probar el funcionamiento de este proyecto, nos apoyaremos de


PostMan para realizar las peticiones HTTP hacía nuestros métodos Api.
Tras compilar, ejecutar y hacer una llamada HTTP Get al método api Get del
WebApi obtenemos el listado de Albumes relacionados con el modelo Artista.
Comprobamos el funcionamiento del método api Create enviando un objeto json
con las propiedades de Album y no olvidar cambiar el tipo de petición a HTTP Post
en PostMan.

El nuevo objeto se creó correctamente, ahora volveremos a realizar la petición al


método Get para comprobar la existencia del nuevo registro en la lista de Albumes.
Como podemos observar está implementación funciona correctamente, hemos
utilizado el patrón repositorio y una unidad de trabajo.
Entre los beneficios de utilizar el patrón repositorio podemos mencionar
centralización de la lógica de acceso a datos, punto de sustitución para las pruebas
unitarias y arquitectura flexible que se puede adaptar a medida que evoluciona el
diseño general de la aplicación.
En cuanto al patrón unidad de trabajo personalmente uso la unidad de trabajo para
reducir mucha inyección de dependencia, puedo tener una unidad de trabajo de la
base de datos y una vez que use la inyección de dependencias para inyectar el
contexto de la Base de datos en esa unidad de trabajo, no necesito inyectar cada
repositorio de modelos donde quiero usarlos, pero solo accederé a los repositorios
desde el unidad de trabajo, esto también me ayuda a crear instancias de un
repositorio solo cuando lo necesito en un método específico.

Conclusión
El patrón repositorio está destinado a crear una capa de abstracción entre la capa
de acceso a datos y la capa empresarial para que pueda ayudar a aislar la
aplicación de los cambios en el almacén de datos y facilitar las pruebas unitarias
automatizadas para el desarrollo basado en pruebas.
En esta implementación hacemos uso de EntityFramework Core en una
implementación de la Unidad de Trabajo y Patrón Repositorio.
Por lo tanto, no es del todo necesario en estos días envolver Entity Framework
Core en un patrón de Unidad de Trabajo, porque básicamente se está envolviendo
una abstracción sobre una abstracción, pero para fines de entender cómo funciona
Unidad de trabajo hacemos uso de Entity Framework Core.
Además, únicamente tenemos un repositorio y el objetivo de la unidad de trabajo es
centralizar y unificar repositorios.
Link al repositorio en Github:
https://github.com/EbarriosCode/RepositoryUnitOfWorkNetCore3

También podría gustarte