Solo tuve que cambiar un ORM y fue una tarea relativamente desalentadora, porque la lógica de consulta se estaba filtrando por todas partes. Si alguna vez hubiera tenido que desarrollar una nueva aplicación, mi preferencia personal sería encapsular toda la lógica de consulta (usando un ORM) para prevenir el cambio en el futuro. El patrón de repositorio es bastante problemático para codificar y mantener, así que me preguntaba si hay algún otro patrón para resolver el problema.
Puedo prever publicaciones sobre no agregar complejidad adicional antes de que sea realmente necesario, ser ágil, etc., pero solo estoy interesado en los patrones existentes para resolver un problema similar de una manera más simple.
Mi primer pensamiento fue tener un repositorio de tipos genéricos, al que agrego métodos según sea necesario para clases específicas de repositorios de tipos a través de métodos de extensión, pero las pruebas unitarias de métodos estáticos son terriblemente dolorosas. ES DECIR:
public static class PersonExtensions
{
public static IEnumerable<Person> GetRetiredPeople(this IRepository<Person> personRep)
{
// logic
}
}
fuente
Respuestas:
En primer lugar: un repositorio genérico debe considerarse una clase base y no implementaciones completas. Debería ayudarlo a implementar los métodos CRUD comunes. Pero aún debe implementar los métodos de consulta:
Segundo:
No regrese
IQueryable
. Es una abstracción permeable. Intente implementar esa interfaz usted mismo o úselo sin conocer el proveedor de base de datos subyacente. Por ejemplo, cada proveedor de db tiene su propia API para cargar entidades con entusiasmo. Por eso es una abstracción permeable.Alternativa
Como alternativa, puede usar consultas (por ejemplo, según lo define el patrón de separación Comando / Consulta). CQS se describe en wikipedia.
Básicamente crea clases de consulta que invoca:
Lo mejor de las consultas es que puede utilizar diferentes métodos de acceso a datos para diferentes consultas sin saturar el código. por ejemplo, puede usar un servicio web en uno, nhibernate en otro y ADO.NET en un tercero.
Si está interesado en una implementación de .NET, lea mi artículo: http://blog.gauffin.org/2012/10/griffin-decoupled-the-queries/
fuente
YourProject.YourDomainModelName.Queries
este, será fácil navegar.Lo primero que creo que digo es que ORM ya es una abstracción lo suficientemente grande sobre su base de datos. Algunos ORM proporcionan enlaces a todas las bases de datos relacionales comunes (NHibernate tiene enlaces a MSSQL, Oracle, MySQL, Postgress, etc.) Por lo tanto, construir nuevas abstracciones no me parece rentable. Además, argumentando que necesita "abstraer" este ORM no tiene sentido.
Si todavía desea construir esta abstracción, iría en contra del patrón de repositorio. Fue genial en la era del SQL puro, pero es bastante problemático frente al ORM moderno. Principalmente porque terminas re-implementando la mayoría de las características de ORM, como las operaciones CRUD y las consultas.
Si tuviera que construir tales abstracciones, usaría estas reglas / patrones
En la implementación concreta, usaría las operaciones CRUD de ORM directamente, sin ningún ajuste. También haría consultas simples directamente en el código. Pero las consultas complejas se encapsularían en sus propios objetos. Para "ocultar" el ORM, intentaría inyectar el contexto de datos de forma transparente en un servicio / objetos de interfaz de usuario y hacer lo mismo para consultar objetos.
Lo último que me gustaría decir es que muchas personas usan ORM sin saber cómo usarlo y cómo obtener el mejor "beneficio". Las personas que recomiendan repositorios suelen ser de este tipo.
Como lectura recomendada, diría el blog de Ayende , especialmente este artículo .
fuente
El problema con la implementación con fugas es que necesita muchas condiciones de filtro diferentes.
Puede reducir esta API si implementa un método de repositorio FindByExample y lo usa así
fuente
Considere hacer que sus extensiones operen en IQueryable en lugar de IRepository.
A prueba unitaria:
No se requiere burlarse de fancing para las pruebas. También puede combinar estos métodos de extensión para crear consultas más complejas según sea necesario.
fuente
IQueryable
es una mala madre, o más bien una interfaz de DIOS. La implementación es muy necesaria y hay muy pocos (si los hay) proveedores completos de LINQ to Sql. b) Los métodos de extensión hacen imposible la extensión (uno de los principios fundamentales de OOP).Escribí un patrón de objeto de consulta bastante bueno para NHibernate aquí: https://github.com/shaynevanasperen/NHibernate.Sessions.Operations
Funciona usando una interfaz como esta:
Dada una clase de entidad POCO como esta:
Puede construir objetos de consulta como este:
Y luego úsalos así:
fuente