¿Cómo debo implementar el patrón de repositorio para modelos de objetos complejos?

21

Nuestro modelo de datos tiene casi 200 clases que se pueden separar en aproximadamente una docena de áreas funcionales. Hubiera sido bueno usar dominios, pero la separación no es tan limpia y no podemos cambiarla.

Estamos rediseñando nuestro DAL para usar Entity Framework y la mayoría de las recomendaciones que he visto sugieren usar un patrón de Repositorio. Sin embargo, ninguna de las muestras realmente trata con modelos de objetos complejos. Algunas implementaciones que he encontrado sugieren el uso de un repositorio por entidad. Esto parece ridículo e insostenible para modelos grandes y complejos.

¿Es realmente necesario crear una UnitOfWork para cada operación y un Repositorio para cada entidad? Podría terminar con miles de clases. Sé que esto no es razonable, pero he encontrado muy poca guía para implementar Repository, Unit Of Work y Entity Framework sobre modelos complejos y aplicaciones comerciales realistas.

Eric Falsken
fuente

Respuestas:

6

Primero, revisará todas las entidades que tenga y se preguntará:

¿Tiene sentido persistir esta entidad solo?

Lo que quiero decir aquí es que en su modelo de objetos, algunas entidades probablemente están contenidas en otras en una relación maestro-detalle. Si su entidad depende en gran medida de otra, no cree un repositorio solo para esta entidad porque es probable que no sea persistente por sí misma. En su lugar, creará un repositorio para cada clase principal y se asegurará de que las entidades secundarias y otras relaciones persistan al mismo tiempo.

No me gusta cómo implementaron el patrón UnitOfWork en el enlace que proporcionó. Te sugiero que hagas algo más en este sentido . No tiene que definir una clase por repositorio. Se puede usar la misma clase para cada repositorio, cada uno con su propia instancia de la clase UnitOfWork durante la vida útil de la operación. También puede reutilizar la misma UnitOfWork en diferentes repositorios para los cambios que desea que persistan al mismo tiempo.

marco-fiset
fuente
Buen enlace! Lo estoy revisando.
Eric Falsken
Su enlace (y respuesta) fueron los más útiles, aunque terminé sin usar los patrones proporcionados. Terminé usando una clase de contenedor que representaba los métodos Agregar / Adjuntar / Eliminar / Guardar Cambios para trabajar como un repositorio genérico, y luego agregué un método Query / QuerySingle / QueryAll que acepta clases de consulta personalizadas para mantener mi implementación de consulta. Esto está funcionando bien para que pueda hacer consultas LINQ y T-SQL sin involucrar directamente a EF.
Eric Falsken
Entity Framework, con su uso de transacciones, ya es una implementación del patrón de Unidad de Trabajo.
Greg Burghardt
1
link is dead ...
Newtopian
3

Tal vez debería echar un vistazo al diseño impulsado por dominio . Recomienda agrupar sus objetos en agregados y crear repositorios solo para la entidad raíz de cada agregado. Es una buena manera de poner orden en un gran modelo de objeto complejo.

Sus diferentes áreas funcionales podrían ser Contextos delimitados . Existen varias técnicas para tratar los contextos limitados superpuestos si la separación entre ellos no está clara.

guillaume31
fuente
0

¿Qué fundamento teórico ha encontrado para el diseño de la base de datos "Patrón de repositorio"? Supongo que ninguno. Es una capa de complejidad que descansa sobre una premisa falsa: que la "capa de persistencia" es algo de lo que necesita estar aislado. Por lo que puedo decir, juega con la ignorancia generalizada de la programación de los principios de diseño relacional, y satisface una centralidad presupuesta del diseño OO de la aplicación. Pero no justifica su existencia por razones racionales, y mucho menos teóricas.

El único camino verdadero al diseño de la base de datos no ha cambiado en 30 años: analice los datos. Encuentra las claves y restricciones y las relaciones de muchos a uno. Diseñe sus tablas de acuerdo con la forma normal de Boyce-Codd. Use vistas y procedimientos almacenados para facilitar el acceso a los datos.

Aunque no sea querido, un DBMS SQL proporciona una mejor capa de aislamiento que cualquier cosa que el programador pueda proporcionar. Es cierto que a medida que la base de datos cambia, el SQL utilizado para acceder podría tener que cambiar. Pero tenga en cuenta que eso es cierto independientemente de si hay o no una capa de mediación . Mientras la aplicación utilice vistas y procedimientos almacenados para acceder al DBMS, las herramientas de ingeniería SQL normales indicarán cuándo los cambios en la base de datos subyacente invalidan esas vistas y procedimientos almacenados.

Ahí radica el desafío, por supuesto. Una capa de mediación proporciona la ilusión de aislamiento y la comodidad para el programador de escribir código, que él sabe cómo hacer. Aprender el diseño de bases de datos y SQL requiere aprender algo nuevo. La mayoría de las personas preferiría morir antes que pensar, y muchas triunfan.

Sin duda, alguien en su equipo objetará que escribir SQL para admitir sus 200 clases es mucho trabajo. Sin duda. Pero al menos es un trabajo útil . Si diseñas una base de datos imitando tu diseño OO, también harás mucho trabajo, en gran parte inútil, y vencerás la mayor parte de lo que te ofrece el DBMS.

Por ejemplo, contempla reflejar la Unidad de trabajo en la base de datos (como tabla o tablas, supongo). Unidad de trabajo es un servicio integrado de la DBMS: begin transaction... la base de datos de actualización ... commit transaction. Nada que modelar, excepto la asignación de sus clases a las tablas de la base de datos en SQL.

Su pregunta fue publicada hace 4 años. Estoy respondiendo porque se "actualizó" de alguna manera recientemente, lo que indica que todavía le interesa a alguien. Espero que mi respuesta aliente al lector a aplicar la teoría relacional básica al problema en lugar de adoptar una solución inútil.

James K. Lowden
fuente