2010-07-16 13 views
6

Esta vez tengo una pregunta más filosófica.MVC: ¿Qué es mejor, un gran repositorio por db o uno por entidad comercial?

La mayoría de los libros/tutoriales de MVC parecen sugerir restringir el alcance de un repositorio a un aspecto del modelo y configurar varios repositorios para cubrir todas las clases de modelos. (Por ejemplo: ProjectRep, UserRep, ImageRep, todos mapeando en el mismo db eventualmente).

Veo cómo eso simplificaría las pruebas unitarias, pero no puedo imaginar cómo funcionaría esto en el mundo real, donde la mayoría de las entidades relaciones entre ellos. Al final, siempre me encuentro con una clase de depósito gigantesca por conexión de BD y un FakeRepository igualmente arcaico para pruebas unitarias.

Entonces, ¿cuál es su opinión? ¿Debo tratar de separar los repositorios? ¿Importa incluso si el ProductRep se refiere a datos en el UserRep y viceversa a través de PurchaseHistory? ¿Cómo se asegurarían los diferentes representantes de que no se bloqueen mutuamente cuando acceden al db individual?

Gracias, Duffy

Respuesta

3

Esto funciona en el mundo real porque hay un solo motor bajo el capó de los repositorios. Esto puede ser ORM como NHibernate o su propia solución. Este motor sabe cómo relacionar objetos, bloquear base de datos, solicitudes de caché, etc. Pero el código comercial no debe conocer estos detalles de infraestructura.

Lo que efectivamente hace cuando termina con un repositorio gigante está exponiendo este único motor al mundo real en su lugar. Por lo tanto, confunde el código de su dominio con detalles específicos del motor que, de lo contrario, se ocultan detrás de las interfaces del repositorio.

S#arp Architecture es una muy buena ilustración de cómo los repositorios que Josh habla están implementados y funcionan. Lea también las mejores prácticas de NHibernate article que explican gran parte del fondo S # arp.

Y francamente, no me puedo imaginar cómo funciona su repositorio gigante en el mundo real. Porque la idea se ve mal y no se puede mantener.

+0

Gracias por sus respuestas reflexivas. Ojalá pudiera marcarlos a todos como respuestas. Supongo que había estado demasiado colgado en una asignación 1: 1 entre el modelo de dominio y DB, pero como todos señalan, los dos pueden ser bestias diferentes por completo. Parece que tendré que leer un poco más sobre los ORM – duffy

2

he descubierto que mediante el uso de genéricos y una interfaz, puede evitar tener que codificar muchos repositorios separados. Si su modelo de dominio está bien factorizado, a menudo puede navegar por gráficos de objetos utilizando los objetos de dominio en lugar de otro repositorio.

public class MyDomainObject : IEntity //IEntity is an arbitrary interface for base ents 
{ 
    public int Id { get; set;} 
    public List<DiffObj> NavigationProp { get; set;} 
    //... and so on... 
} 

public interface IRepository<T> where T : IEntity, class, new() 
{ 
    void Inert(T entity); 
    T FindById(int id); 
    //... and so on 
} 

El uso es muy sencillo, y mediante el uso de la COI se puede desacoplar por completo la aplicación del resto de su aplicación:

public class MyBusinessClass 
{ 
    private IRepository<SomeDomainObject> _aRepo; 
    public MyBusinessClass(IREpository<SomeDomainObject> aRepo) 
    { 
      _aRepo = aRepo; 
    } 
    //...and so on 
} 

Esto hace que la unidad de escritura de prueba en un instante real.

+1

Eche un vistazo a esta respuesta sobre cómo implementar esto con IoC para administrar los controladores también - http://stackoverflow.com/questions/2797047/how-do-i-correctly-use-unity-to-pass-a -connectionstring-to-my-repository-classes/2797264 # 2797264 –

+0

Soy fan de la unidad - esp. con las mejoras que han hecho en 2.0. Lo he usado en proyectos de MVC para hacer exactamente eso. –

+0

+1 a esto. recuerde, un IRepository <> no sabe cómo se implementa, y tampoco lo hace la persona que llama. la persona que llama solo quiere el objeto modelo. si usa un ORM para su implementación de IRepository <>, se encargará de que se cargue todo el FK. de lo contrario, puede hacerlo de la forma que desee de forma manual, siempre que la interfaz no cambie y no haya acoplamiento de la interfaz a la implementación. –

Cuestiones relacionadas