A medida que profundizo en el DbContext, DbSet y las interfaces asociadas, me pregunto por qué necesitaría implementar un repositorio "genérico" separado alrededor de estas implementaciones.
Parece que DbContext e IDbSet hacen todo lo que necesita e incluyen la "Unidad de trabajo" dentro de DbContext.
¿Me estoy perdiendo algo aquí o parece que a la gente le gusta agregar otra capa de dependencia sin ninguna razón?
repository-pattern
entity-framework-4.1
unit-of-work
Code Jammr
fuente
fuente
Respuestas:
En realidad tienes razón.
DbContext
es una implementación del patrón de unidad de trabajo yIDbSet
es una implementación del patrón de repositorio.Los repositorios son actualmente muy populares y utilizados en exceso. Todos los usan solo porque hay docenas de artículos sobre la creación de repositorios para el marco de la entidad, pero en realidad nadie describe los desafíos relacionados con esta decisión.
Las razones principales para usar el repositorio son generalmente:
La primera razón es algún tipo de pureza arquitectónica y una gran idea de que si hace que sus capas superiores sean independientes de EF, más adelante puede cambiar a otro marco de persistencia. ¿Cuántas veces viste algo así en el mundo real? Esta razón hace que trabajar con EF sea mucho más difícil porque su repositorio debe exponer muchas características adicionales que envuelven lo que EF permite por defecto.
Al mismo tiempo, envolver el código EF puede mantener su código mejor organizado y siguiendo la regla de separación de preocupaciones. Para mí, esta puede ser la única ventaja real del repositorio y la unidad de trabajo, pero debe comprender que seguir esta regla con EF hará que su código sea más fácil de mantener y de leer, pero en el esfuerzo inicial para crear su aplicación será mucho mayor y para aplicaciones más pequeñas esto puede ser una complejidad innecesaria.
La segunda razón es parcialmente correcta. La gran desventaja de EF es la arquitectura rígida que apenas se puede burlar, por lo que si desea probar la capa superior de la unidad, debe envolver EF de alguna manera para permitir burlarse de su implementación. Pero esto tiene muchas otras consecuencias que describí aquí .
Yo sigo el blog de Ayende . Si alguna vez usó NHibernate, probablemente conozca sus artículos. Este chico recientemente escribió varios artículos en contra del uso del repositorio con NHibernate, pero NHibernate es mucho mejor para burlarse.
fuente
IDbSet
que también puede definir una interfaz personalizada en su contexto derivado, pero eso es todo. Una vez que su código use ChangeTracker, Entradas o cualquier otra cosa, requerirá un gran esfuerzo para envolverlos a todos.IQueryable
o aceptaExpression<>
como parámetro que se coloca internamente en la consulta Linq a entidades, está definiendo la lógica fuera del componente simulado con efectos secundarios que no se pueden probar con pruebas unitarias.Estoy luchando con los mismos problemas, y la simulación para la prueba unitaria de las capas EF es importante. Pero me encontré con este gran artículo que explica cómo configurar el EF 4.1 DbContext para que se pueda simular asegurándose de que su DbContext derivado implemente una interfaz genérica y exponga IDbSet en lugar de DbSet. Como estoy usando un enfoque de Base de datos primero, debido a que nuestra base de datos ya existe, simplemente modifiqué las plantillas T4 utilizadas para generar mi DbContext derivado para generar que devuelva interfaces IDbSet, así como derivar de mi interfaz genérica. De esa manera, todo se puede burlar fácilmente, y no necesita implementar su propia Unidad de trabajo o patrón de repositorio. Simplemente escriba su código de servicio para consumir su interfaz genérica, y cuando vaya a la unidad, pruébelo,
http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/
fuente
Una razón para crear el repositorio es para que pueda ocultar la implementación de DBSet y DbContext si decide pasar de EntityFramework a otra cosa o viceversa.
Por ejemplo, estaba usando NHibernate y envolví todas las llamadas a ese marco dentro de mis clases de repositorio. Devuelven IEnumerable para que sean "genéricos" y mis repositorios tienen las operaciones CRUD estándar (actualizar, eliminar, etc.). Hace mucho tiempo que me mudé a Entity Framework. Al hacerlo, no necesitaba cambiar nada en mis clases de ViewModel o más allá porque señalaban a mi repositorio; solo necesitaba cambiar el interior de mi repositorio. Esto hizo la vida mucho más fácil al migrar.
(Utilicé NHibernate porque nos estamos conectando a ISeries, y en ese momento, no había implementaciones rentables que usaran EF con ISeries. El único disponible era pagar $ 12,000 a IBM por su DB2Connect)
fuente