2011-06-08 14 views
7

El patrón de repositorio parece funcionar bien cuando se trabaja con un proyecto inicial con varias tablas principales grandes.¿Cuál es la mejor práctica para el patrón de repositorio - Repo por tabla?

Sin embargo, a medida que el proyecto crece parece un poco inflexible. Supongamos que tiene muchas tablas secundarias que cuelgan de la tabla principal, ¿necesita un repositorio para cada tabla?

E.g.

CustomerAddress registro tiene siguientes niño tablas:

-> Condado de

-> País

-> CustomerType

En la interfaz de usuario, 3 listas desplegables necesario mostrar, pero se pone un poco tedioso escribiendo un repositorio para cada una de las tablas anteriores que selecciona los datos para las listas desplegables.

¿Existe alguna forma mejor o más eficaz de hacer esto?

Como ejemplo digamos que tiene un repositorio principal de CustomerAddress que supongo que es el 'agregado de raíz' que hereda las operaciones principales de CRUD desde la interfaz de repositorio base.

Anteriormente he recortado la raíz agregada y voy directamente al contexto para este tipo de tablas.

p. Ej.

public Customer GetCustomerById(int id) 
{ 
    return Get(id); 
} 

public IEnumerable<Country> GetCountries() 
{ 
    return _ctx.DataContext.Countries.ToList(); 
} 

etc ...

Pero a veces no se siente derecha, ya que los países que no son parte del cliente, pero me siento como que necesito para virar hacia algo sin tener que crea tropecientos de repositorios para cada tabla. Un repositorio por mesa definitivamente tampoco me parece correcto.

+0

también. imho a 'Country' no se destruirá solo porque elimine una' CustomerAddress'. Creo que continuaría prosperando. No es un agregado infantil. – jgauffin

+0

evitar repositorios con ORM;) http: // ayende.com/blog/3955/repository-is-the-new-singleton – fex

Respuesta

0

Estoy respondiendo mi propia pregunta aquí porque si bien las sugerencias son ciertamente útiles, creo que tengo una mejor solución. Aunque no tengo que crear físicamente el repositorio subyacente para cada tabla ya que tengo una clase base de repositorio genérico con interfaz (Obtener, Agregar, Eliminar), aún tengo que:

1) escribir la interfaz para acceder a cualquiera de los métodos especializados (por lo general éstos son consultas)

2) escribir esas implementaciones

que no necesariamente quieren hacer esto cuando lo único que quiero es recuperar una lista de países o algún tipo sencillo para poblar un menú desplegable. Piense en el esfuerzo requerido si tiene 10 tablas de tipos de referencia.

Lo que decidí hacer fue crear una nueva clase llamada SimpleRepo con interfaz ISimpleRepo que expone 1-2 métodos. Si bien normalmente no me gusta exponer la interfaz IQueryable fuera de la clase repo i/f, no me importa aquí ya que quiero la flexibilidad proporcionada. Simplemente puedo exponer un método 'Query()' que proporciona el gancho de flexibilidad. Puede que necesite esto para especializar el orden o el filtrado.

Cuando un servicio necesita hacer uso de algunos datos simples, se pasa la interfaz ISimple < T>, donde T es la tabla/clase.

Ahora evito la necesidad de crear una interfaz/clase para estos simples datos. ¿Alguien piensa?

0

Primero, el código que ha publicado no es el patrón de repositorio. ¿Dónde está la colección como interfaz? Si es un agregado, solo debe devolver el tipo agregado.

El patrón de repositorio no ofrece mucha flexibilidad cuando se trata de poder seleccionar diferentes tipos. El patrón de repositorio sigue una interfaz de colección (insertar/agregar/actualizar/eliminar/obtener/etc.), reflejando una cosa en memoria, y generalmente solo recupera en tipo. Entonces, si tuviera que usar el patrón de repositorio, necesitaría seleccionar todas las direcciones de clientes y luego * filtrar los países. Sugeriría que se mueva a un patrón diferente, que permita una mayor flexibilidad alias DAO.

Si estas cosas se van a mantener siempre a través de CustomerAddress, cambie los patrones y cree una clase DAO que ofrezca otros getters para los otros tipos de cosas que necesita.


En un plano más genérico, acumulación de necesidad.

Nunca crees ciegamente clases de repositorios, es una pesadilla de mantenimiento. La única vez que discutiría un repositorio por mesa es cuando le gusta el CMS y necesita poder crear todo.

Ejemplo:

para que tenga una CustomerAddress la que une un cliente y un país, pero hay algún otro proceso que tiene que ser capaz de crud el País. Como resultado, necesita * el repositorio para manipular el país y si está siguiendo SECO no quiere tener una lógica duplicada para manipular los países. Lo que tendría es un Respotitory del Cliente que usa el repositorio Country.

+0

lo siento, he actualizado mi código de muestra. – jaffa

+0

@jaffa No veo un cambio? – Nix

+0

Cambié las firmas de función para mostrar que GetCustomerById devuelve un objeto concreto del repositorio y que los países son un objeto de colección. – jaffa

2

No crearía un repositorio por tabla. Por el contrario: definiría un repositorio genérico que funciona para todas las tablas. Al hacer esto, se ahorra una gran cantidad de código, y cuando implementa IQueryable en esa clase, le permitirá usar consultas LINQ sobre él, y puede ocultar su marco O/RM detrás de una abstracción, lo que le permite escribir efectivamente pruebas unitarias Escribí un artículo sobre esto, vea Faking your LINQ provider.

+0

Ya estoy implementando una clase de repositorio base para la clase, pero aún tengo que crear una clase de repo especializada con i/f para cada tabla. No entiendo cómo puedo pasar una lista de países a mi viewModel sin implementar un CountryRepo de alguna manera? – jaffa

+0

Si observa el artículo que menciono, verá que defino una única unidad de clase de trabajo que contiene todos los repositorios como propiedades. Agregar un nuevo repositorio significa simplemente agregar una nueva propiedad a la unidad de trabajo, sin agregar una nueva clase de repositorio. – Steven

0

Respondiendo a la pregunta own answer: Esto no tiene sentido para mí; aunque es posible que todavía tengas un buen caso de uso, no te estoy siguiendo. Puntos 1 y 2 ... si necesita métodos especializados, parece que pertenecen a su propio repositorio. Punto 2: sí, eso necesita una implementación.

Compartiendo entre repositorios, con el pequeño repo siendo la pregunta (es necesario), aprecio esa pregunta/problema, pero los chicos en este hilo me llevaron a estar bien con 1 repo por mesa, incluida la posibilidad de tener una 'capa de servicio', aunque no dieron ningún ejemplo de eso, y aún no lo he probado (actualmente mi práctica, para bien o para mal, ha sido tener el mayor repo compartir o instanciar el más pequeño) uno que necesita):

One repository per table or one per functional section?

Cuestiones relacionadas