pattern mvc hamedani genericrepository framework antipattern c# entity-framework repository-pattern

c# - mvc - ¿Por qué usar el patrón de repositorio o por favor explícamelo?



repository pattern c# entity framework core (8)

Estoy aprendiendo el patrón de repositorio y estaba leyendo Repository Pattern con Entity Framework 4.1 y Code First y Generic Repository Pattern - Entity Framework, ASP.NET MVC y Unit Testing Triangle sobre cómo implementan el patrón de repositorio con Entity Framework.

Diciendo

• Ocultar EF de la capa superior
• Hacer código mejor comprobable

Haga que el código sea mejor comprobable. Entiendo, pero ¿por qué ocultar EF de la capa superior?

Al observar su implementación, parece que simplemente envuelve el marco de la entidad con un método genérico para consultar el marco de la entidad. En realidad, ¿cuál es el motivo para hacer esto?

Estoy asumiendo que es para

  1. Acoplamiento flojo (¿por qué ocultar EF de la capa superior?)
  2. Evite repetir la escritura de la misma declaración LINQ para la misma consulta

¿Lo entiendo bien?

Si escribo un DataAccessLayer que es una clase, tengo métodos

QueryFooObject(int id) { ..//query foo from entity framework } AddFooObject(Foo obj) { .. //add foo to entity framework } ...... QueryBarObject(int id) { .. } AddBarObject(Bar obj) { ... }

¿Es eso también un patrón de repositorio?

La explicación para el muñeco será genial :)


Cuando está diseñando sus clases de repositorio para que se parezcan a un objeto de dominio, para proporcionar el mismo contexto de datos a todos los repositorios y facilitar la implementación de la unidad de trabajo, el patrón de repositorio tiene sentido. Por favor encuentre abajo algún ejemplo inventado.

class StudenRepository { dbcontext ctx; StundentRepository(dbcontext ctx) { this.ctx=ctx; } public void EnrollCourse(int courseId) { this.ctx.Students.Add(new Course(){CourseId=courseId}); } } class TeacherRepository { dbcontext ctx; TeacherRepository(dbcontext ctx) { this.ctx=ctx; } public void EngageCourse(int courseId) { this.ctx.Teachers.Add(new Course(){CourseId=courseId}); } } public class MyunitOfWork { dbcontext ctx; private StudentRepository _studentRepository; private TeacherRepository _teacherRepository; public MyunitOfWork(dbcontext ctx) { this.ctx=ctx; } public StudentRepository StundetRepository { get { if(_studentRepository==null) _stundentRepository=new StundetRepository(this.ctx); return _stundentRepository; } } public TeacherRepository TeacherRepository { get { if(_teacherRepository==null) _teacherRepository=new TeacherRepository (this.ctx); return _teacherRepository; } } public void Commit() { this.ctx.SaveChanges(); } } //some controller method public void Register(int courseId) { using(var uw=new MyunitOfWork(new context()) { uw.StudentRepository.EnrollCourse(courseId); uw.TeacherRepository.EngageCourse(courseId); uw.Commit(); } }


Esta imagen hace que sea fácil de entender


La misma razón por la que no codifica las rutas de archivos en su aplicación: acoplamiento flexible y encapsulation . Imagine una aplicación con referencias codificadas en "c: / windows / fonts" y los problemas que pueden causar. No deberías codificar las referencias a las rutas, ¿por qué deberías codificar las referencias a tu capa de persistencia? Oculte sus rutas detrás de la configuración de configuración (o carpetas especiales o lo que sea compatible con su sistema operativo) y oculte su persistencia detrás de un repositorio. Será mucho más fácil probar la unidad, implementarla en otros entornos, intercambiar implementaciones y razonar sobre los objetos de su dominio si los problemas de persistencia están ocultos detrás de un repositorio.


Los sistemas de repositorio son buenos para probar.

Una de las razones es que puedes usar la Inyección de Dependencia.

Básicamente, usted crea una interfaz para su repositorio, y hace referencia a la interfaz cuando hace el objeto. Luego puedes crear un objeto falso (usando moq por ejemplo) que implementa esa interfaz. Usando algo como ninject, puedes vincular el tipo apropiado a esa interfaz. Boom acabas de quitar una dependencia de la ecuación y la reemplazaste con algo comprobable.

La idea es poder intercambiar fácilmente implementaciones de objetos para fines de prueba. Espero que tenga sentido.


No creo que debas.

El Entity Framework ya es una capa de abstracción sobre su base de datos. El contexto usa el patrón de unidad de trabajo y cada DBSet es un repositorio. Agregar un patrón de repositorio en la parte superior de esta distancia lo aleja de las características de su ORM.

Hablé de esto en mi blog: http://www.nogginbox.co.uk/blog/do-we-need-the-repository-pattern

La razón principal para agregar su propia implementación de repositorio es para que pueda usar la inyección de dependencia y hacer que su código sea más comprobable.

EF no se puede probar de inmediato, pero es bastante fácil crear una versión simulada del contexto de datos de EF con una interfaz que se puede inyectar.

Hablé de eso aquí: http://www.nogginbox.co.uk/blog/mocking-entity-framework-data-context

Si no necesitamos el patrón de repositorio para hacer que EF se pueda probar, entonces no creo que lo necesitemos en absoluto.


Sé que es malo proporcionar enlaces en respuesta aquí; sin embargo, quería compartir el video que explica varias ventajas de Repository Pattern al usarlo con Entity framework. A continuación se muestra el enlace de youtube.

https://www.youtube.com/watch?v=rtXpYpZdOzM

También proporciona detalles sobre cómo implementar el patrón Repository correctamente.


También es una ventaja mantener sus consultas en un lugar central; de lo contrario, sus consultas se dispersarán y serán más difíciles de mantener.

Y el primer punto que mencionas: "ocultar EF" es algo bueno. Por ejemplo, guardar la lógica puede ser difícil de implementar. Existen múltiples estrategias que se aplican mejor en diferentes escenarios. Especialmente cuando se trata de salvar entidades que también tienen cambios en entidades relacionadas.

El uso de repositorios (en combinación con UnitOfWork) también puede centralizar esta lógica.

Here hay algunos videos con una buena explicación.


Una cosa es aumentar la capacidad de prueba y tener un acoplamiento flexible a la tecnología de persistencia subyacente. Pero también tendrá un repositorio por objeto raíz agregado (por ejemplo, un pedido puede ser un directorio agregado, que también tiene líneas de orden (que no son una raíz agregada), para hacer que la persistencia del objeto de dominio sea más genérica.

También hace que sea mucho más fácil administrar objetos, porque cuando guardas un pedido, también guardará tus elementos secundarios (que pueden ser líneas de pedido).