Creo que si tiene sus repositorios use un ORM que ya está lo suficientemente abstraído de la base de datos.
Sin embargo, donde estoy trabajando ahora, alguien cree que deberíamos tener una capa que abstraiga el ORM en caso de que nos gustaría cambiar el ORM más adelante.
¿Es realmente necesario o es simplemente una gran cantidad de gastos generales para crear una capa que funcione en muchos ORM?
Editar
Solo para dar más detalles:
- Tenemos clase POCO y clase de entidad que están mapeadas con AutoMapper. La capa de repositorio utiliza la clase de entidad. La capa de repositorio luego usa la capa adicional de abstracción para comunicarse con Entity Framework.
- La capa empresarial no tiene acceso directo a Entity Framework. Incluso sin la capa adicional de abstracción sobre el ORM, esta necesita usar la capa de servicio que usa la capa de repositorio. En ambos casos, la capa empresarial está totalmente separada del ORM.
- El argumento principal es poder cambiar ORM en el futuro. Dado que está realmente localizado dentro de la capa del Repositorio, para mí, ya está bien separado y no veo por qué se requiere una capa adicional de abstracción para tener un código de "calidad".
Respuestas:
De esa manera se encuentra la locura. Es muy poco probable que alguna vez necesite cambiar ORM. Y si alguna vez decide cambiar el ORM, el costo de reescribir las asignaciones será una pequeña fracción del costo para desarrollar y mantener su propio meta-ORM. Esperaría que pudiera escribir algunos scripts para hacer el 95% del trabajo necesario para cambiar ORM.
Los marcos internos son casi siempre un desastre. Construir uno anticipándose a las necesidades futuras es casi un desastre garantizado. Los marcos exitosos se extraen de proyectos exitosos, no se construyen con anticipación para satisfacer necesidades imaginarias.
fuente
El ORM proporciona una abstracción para que su capa de datos sea independiente de su RDBMS, pero puede no ser suficiente para "desatar" su capa empresarial de su capa de datos. Específicamente, no debe permitir que los objetos que se asignan a tablas RDBMS se "filtren" directamente en la capa empresarial.
Como mínimo, su capa empresarial necesita programar en interfaces que sus objetos mapeados en tabla y administrados por ORM de la capa de datos podrían implementar. Además, es posible que deba crear una capa basada en la interfaz de construcción de consultas abstractas para ocultar las capacidades de consulta nativas de su ORM. El objetivo principal es evitar "introducir" cualquier ORM particular en su solución más allá de su capa de datos. Por ejemplo, puede ser tentador crear cadenas HQL ( Hibernate Query Language ) en la capa empresarial. Sin embargo, esta decisión aparentemente inocente vincularía su capa empresarial con Hibernate, lo que uniría a la empresa y las capas de acceso a datos; Debe intentar evitar esta situación tanto como sea posible.
EDITAR: en su caso, la capa adicional dentro del repositorio es una pérdida de tiempo: según su punto número dos, su capa empresarial está suficientemente aislada de su repositorio. Proporcionar aislamiento adicional introduciría una complejidad innecesaria, sin beneficios adicionales.
El problema con la construcción de una capa de abstracción adicional dentro de su repositorio es que la "marca" particular de ORM dicta la forma en que interactúa con él. Si crea un envoltorio delgado que se parece a su ORM, pero está bajo su control, reemplazar el ORM subyacente será aproximadamente tan difícil como lo sería sin esa capa adicional. Si, por otro lado, construye una capa que no se parece en nada a su ORM, entonces debe cuestionar su elección de la tecnología de mapeo relacional de objetos.
fuente
UnitOfWork generalmente proporciona esta abstracción. Es un lugar que necesita cambiar, sus repositorios dependen de él a través de una interfaz. Si alguna vez necesita cambiar O / RM, simplemente implemente un nuevo UoW sobre él. Uno y listo.
Por cierto, va más allá de simplemente cambiar O / RM, piense en las pruebas unitarias. Tengo tres implementaciones de UnitOfWork, una para EF, una para NH (porque realmente tuve que cambiar las O / RM a mitad del proyecto para un cliente que quería soporte de Oracle), y una para la persistencia de InMemory. La persistencia de InMemory era perfecta para pruebas unitarias o incluso para la creación rápida de prototipos antes de que estuviera listo para poner una base de datos detrás de ella.
El marco es simple de implementar. Primero tienes tu interfaz genérica IRepository
Y la interfaz IUnitOfWork
El siguiente es el repositorio base (su elección sobre si debe ser abstracto o no)
Implementar IUnitOfWork es un juego de niños para EF, NH e In Memory. La razón por la que devuelvo IQueryable, es por la misma razón, mencionó Ayende en su publicación, el cliente puede filtrar, ordenar, agrupar e incluso proyectar aún más el resultado usando LINQ y aún obtendrá el beneficio de que todo se haga desde el lado del servidor.
fuente