Dónde ubicar mis consultas: modelo vs. controlador

architecture asp.net-mvc-3 dapper

Pregunta

Acabo de cambiar de ActiveRecord / NHibernate a Dapper . Anteriormente, tenía todas mis consultas en mis controladores. Sin embargo, algunas propiedades que fueron convenientes para implementar en mis modelos (como resúmenes / sumas / totales / promedios), pude calcular iterando sobre variables de instancia (colecciones) en mi modelo.

Para ser específico, mi Project tiene una noción de AppSessions , y puedo calcular el número total de sesiones, más la duración promedio de la sesión, iterando sobre someProject.AppSessions .

Ahora que estoy en Dapper, esto parece confuso: mis métodos de control ahora hacen consultas a la base de datos a través de Dapper (lo cual parece correcto), pero mi clase de modelo también realiza consultas a la base de datos a través de Dapper (lo que parece extraño).

TLDR: ¿Debería ir el acceso a la base de datos en mi modelo, o controlador, o en ambos? Parece que ambos no son correctos, y me gustaría limitarlo a una "capa" para que el cambio de estilo de acceso a la BD más tarde no afecte demasiado.

Respuesta aceptada

Debes considerar usar un patrón de repositorio :

Con los repositorios, todas las consultas de la base de datos se encapsulan en un repositorio que se expone a través de la interfaz pública, por ejemplo:

public interface IGenericRepository<T> where T : class
{
    T Get(object id);
    IQueryable<T> GetAll();
    void Insert(T entity);
    void Delete(T entity);
    void Save(T entity);
}

Entonces puedes inyectar un repositorio en un controlador:

public class MyController
{
    private readonly IGenericRepository<Foo> _fooRepository;
    public MyController(IGenericRepository<Foo> fooRepository)
    {
        _fooRepository = fooRepository;
    }   
}

Esto mantiene la UI libre de cualquier dependencia de DB y facilita las pruebas; de las pruebas unitarias puedes inyectar cualquier simulación que implemente IRepository. Esto también permite que el repositorio implemente y cambie entre tecnologías como Dapper o Entity Framework sin ningún cambio de cliente y en cualquier momento.

El ejemplo anterior utilizó un repositorio genérico, pero no es necesario; puede crear una interfaz separada para cada repositorio, por ejemplo, IFooRepository.

Hay muchos ejemplos y muchas variaciones de cómo se puede implementar el patrón de repositorio, así que google algo más para entenderlo. Aquí está uno de mis artículos favoritos. estructuras en capas .

Otra nota: para proyectos pequeños, debería estar bien enviar consultas directamente a los controladores ...


Respuesta popular

Estoy de acuerdo con @ void-ray con respecto al modelo de repositorio. Sin embargo, si no desea acceder a interfaces e inyección de dependencias, puede separar la capa de acceso a datos y usar métodos estáticos para devolver datos de Dapper.

Cuando estoy usando Dapper, normalmente tengo una biblioteca Repository que devuelve objetos muy pequeños o listas que luego pueden mapearse en un ViewModel y pasarse a la View (la asignación es realizada por StructureMap, pero podría manejarse en el controlador u otro helper) .



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow