2010-04-21 13 views
32

Todo lo que estoy tratando de encontrar es la definición correcta del patrón de repositorio.Patrón de repositorio Estandarización de métodos

Mi entendimiento original fue esto (muy dumbed abajo)

  • separar sus objetos comerciales de sus Datos Objetos
  • estandarizar los métodos de acceso en la capa de acceso de datos.

Realmente he visto 2 implementaciones diferentes, y no hay ejemplos formales en línea, los que he visto están escondidos en los libros.

Implementación 1:

public Interface IRepository<T>{ 
     List<T> GetAll(); 
     void Create(T p); 
     void Update(T p); 
} 


public interface IProductRepository: IRepository<Product> { 
     //Extension methods if needed 
     List<Product> GetProductsByCustomerID(); 
} 

Aplicación 2:

public interface IProductRepository { 
     List<Product> GetAllProducts(); 
     void CreateProduct(Product p); 
     void UpdateProduct(Product p); 
     List<Product> GetProductsByCustomerID(); 
} 

Aviso la primera es genérico Obtener/Actualización/GetAll, etc, el segundo es más de lo Definiría "DAO" como.

Ambos comparten una extracción de sus entidades de datos. Lo cual me gusta, pero puedo hacer lo mismo con un simple DAO. Sin embargo, la segunda pieza estandariza las operaciones de acceso en las que veo valor, si implementa esta empresa, las personas fácilmente conocerían el conjunto de métodos de acceso para su repositorio.

¿Me equivoco al asumir que la estandarización del acceso a los datos es una pieza integral de este patrón? Si ambos son correctos, ¿por qué elegir uno hacer la implementación 2?

Rhino tiene un buen artículo sobre la implementación 1, y por supuesto MS tiene un vago definition y un ejemplo de implementación 2 es here.

+0

Para mí, una _interfaz_ es una abstracción, es decir, lo opuesto a _implementation_. ¿Estamos discutiendo solo las interfaces aquí, o más bien las clases de implementación? – MEMark

Respuesta

14

I segundo la cita de Fowler citada por oded. Quiero señalar que dijo "collection- like" interfaz. La forma en que implemente la interfaz tipo colección depende de usted, pero ni puede ni debe tratar de ocultar el hecho de que representa una fuente de datos remota. Por lo tanto, difiere significativamente de una colección en memoria, que no necesita enjuagar los cambios en un almacén de datos remoto. El mecanismo de seguimiento de cambios de su ORM o su solución Roll-Your-Own determina qué tan transparente se puede hacer esto con la persona que llama. Por lo general, las eliminaciones deben marcarse explícitamente, las inserciones son reconocibles (persistencia por accesibilidad) y las actualizaciones a veces también deben marcarse explícitamente. Combina esto con las complicadas dependencias de tus raíces agregadas y verás que no es muy similar a la colección.

No existe la "implementación del repositorio canónico".

Hay una batalla constante entre los defensores de una clase base de repositorio genérico y aquellos que prefieren implementar cada repositorio por sí mismo. Si bien la implementación genérica es atractiva en escenarios simples, muy a menudo encontrará que es una abstracción muy permeable. Por ejemplo, algunos de sus agregados solo se pueden eliminar por software (se pueden dividir por omisión de métodos virtuales), mientras que otros pueden no admitir una operación de eliminación.

Asegúrese de comprender las implicaciones de cada enfoque antes de decidir qué ruta tomar. Greg Young tiene una buena publicación sobre los méritos de los repositorios genéricos.

http://codebetter.com/blogs/gregyoung/archive/2009/01/16/ddd-the-generic-repository.aspx

7

De Martin Fowler "Patrones de Arquitectura de aplicaciones empresariales", la definición del modelo de repositorio es:

media entre el dominio y datos de mapeo capas utilizando una interfaz similar a la colección para acceder a los objetos de dominio.

Por lo tanto, ambos enfoques son correctos.

+0

Supongo que toda la "colección-como" es vaga, yo diría que una colección como la de Get/Update/Remove/etc no ... pero supongo que usted diría lo mismo que Get = GetProduct – Nix

4

Soy un gran admirador del patrón de repositorio genérico, pero creo que debería considerar no heredar directamente de la interfaz, ya que puede convertirse en una limitación muy grande, especialmente porque muchas veces el código de la interfaz genérica será el mismo que podría definirse en una clase base abstracta que ya no podrá tener más de 1 repositorio genérico dentro de una clase.

Recomiendo que su implementador de IProductRepository acceda al IRepository<Product> genérico a través de la delegación e inyecte eso en el constructor para que pueda componer su clase de posibles muchos IRepositories y agruparlos detrás de una sola interfaz de una manera que tenga sentido.

escribí un blog sobre este tema mientras se hace referencia específicamente a NHibernate este patrón se puede aplicar a cualquier tipo de repositorio: Creating a common generic and extensible NHiberate Repository version 2

2

Con la introducción de LINQ en .NET, un patrón repositorio genérico se hace mucho más fácil de realizar :

public interface IRepository<T> : IQueryable<T> 
{ 
    void Add(T item); 
    void Remove(T item); 
} 

para calificar como un repositorio, simplemente tiene que ser capaz de acceder a los datos en el almacén subyacente (fácilmente proporcionada por IQueryable) y modificar los datos contenidos.

Puede proporcionar extensiones a la interfaz base para proporcionar ganchos para un comportamiento más específico de la entidad (como el cableado en una llamada de procedimiento almacenado para un repositorio basado en SQL), pero la mayoría de las operaciones se pueden completar mediante la interfaz simple .

1

Además de su interfaz genérica repositorio (aplicación 1) y su variación en el repositorio de la función específica (aplicación 2) también se puede considerar un método genérico repositorio:

public interface IRepository 
{ 
    void Save<ENTITY>(ENTITY entity) where ENTITY : DomainEntity; 

    ENTITY Load<ENTITY>(Guid id) where ENTITY : DomainEntity; 

    IQueryable<ENTITY> Query<ENTITY>() where ENTITY : DomainEntity; 

    IQueryable<ENTITY> Query<ENTITY>(IDomainQuery<ENTITY> whereQuery) 
     where ENTITY : DomainEntity; 
} 

Este la tercera versión proviene de this blogpost por Jimmy Bogard, donde también expresa preferencia por la interfaz genérica del repositorio. Normalmente lo sigo con una clase base de repositorio genérico que implementa esta interfaz; De esa forma, solo tengo que implementar las cosas que son diferentes para cada entidad de dominio.

0

Suelo usar el repositorio genérico con composición en lugar de herencia. Eso me da la ventaja de una implementación genérica, con el control de qué métodos exponer.

Algo como esto:

public Interface IRepository<T>{ 
    List<T> GetAll(); 
    void Create(T p); 
    void Update(T p); 
} 


public interface IProductRepository { 
    //Extension methods if needed 
    List<Product> GetProductsByCustomerID(); 
    List<T> GetAll(); 
    void Create(T p); 
    //Let assume here you should not be able to update the products 
} 

public ProductRepository : IProductRepository { 
    private IRepository _repository; 

    public ProductRepository(IRepository repository) { 
     this._repository = repository; 
    } 

     List<T> GetAll() 
     { 
      _repository.GetAll(); 
     } 

     void Create(T p) 
     { 
      _repository.Create(p); 
     } 

     List<Product> GetProductsByCustomerID() 
     { 
      //..implementation goes here 
     } 
} 
0

El patrón repositorio es uno de los patrones más utilizado en el desarrollo de software. Hay muchas publicaciones que se pueden marcar como respuesta a su pregunta. Algo que me gustaría destacar es el hecho de que una buena implementación de repositorio se mejorará si usa IoC (Autofac, Windsor, etc.). He estado jugando hace mucho tiempo con algunos marcos basados ​​en ADO.NET (LinqToSql, EF) y NHibernate. Siempre puede obtener beneficios de una implementación genérica si usa IoC. Puede definir interfaces para sus repositorios específicos y resolver cuando realmente necesita algunas acciones específicas.

Cuestiones relacionadas