Où placer mes requêtes - modèle vs contrôleur

architecture asp.net-mvc-3 dapper

Question

Je viens de passer d'ActiveRecord / NHibernate à Dapper . Auparavant, j'avais toutes mes requêtes dans mes contrôleurs. Cependant, certaines propriétés qui étaient pratiques à mettre en œuvre sur mes modèles (comme les résumés / sommes / totaux / moyennes), je pouvais calculer en itérant sur les variables d’instance (collections) de mon modèle.

Pour être précis, mon Project a une notion de AppSessions d’ AppSessions , et je peux calculer le nombre total de sessions, plus la durée moyenne des sessions, en someProject.AppSessions une itération sur someProject.AppSessions .

Maintenant que je suis dans Dapper, cela semble confus: mes méthodes de contrôleur envoient désormais des requêtes à la base de données via Dapper (ce qui semble correct), mais ma classe de modèle effectue également des requêtes sur Dapper (ce qui semble étrange).

TLDR: L'accès à la base de données doit-il être intégré à mon modèle, à mon contrôleur ou aux deux? Il semble que les deux ne soient pas corrects, et je voudrais le limiter à un seul "calque", de sorte que le changement ultérieur du style d'accès à la base de données n'aura pas trop d'impact.

Réponse acceptée

Vous devriez envisager d'utiliser un modèle de référentiel :

Avec les référentiels, toutes les requêtes de base de données sont encapsulées dans un référentiel exposé via une interface publique, par exemple:

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);
}

Ensuite, vous pouvez injecter un référentiel dans un contrôleur:

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

Cela permet de garder l'interface libre de toute dépendance à la base de données et facilite les tests. à partir des tests unitaires, vous pouvez injecter n'importe quelle maquette implémentant IRepository. Cela permet également au référentiel d'implémenter et de basculer entre des technologies telles que Dapper ou Entity Framework sans aucune modification du client et à tout moment.

L'exemple ci-dessus utilise un référentiel générique, mais vous n'êtes pas obligé de le faire. vous pouvez créer une interface distincte pour chaque référentiel, par exemple IFooRepository.

Il existe de nombreux exemples et de nombreuses variantes de la façon dont le modèle de référentiel peut être implémenté. Voici l'un de mes articles préférés re. architectures en couches .

Autre remarque: pour les petits projets, il convient de placer les requêtes directement dans les contrôleurs ...


Réponse populaire

Je suis d'accord avec @ void-ray en ce qui concerne le modèle de référentiel. Cependant, si vous ne voulez pas entrer dans les interfaces et injecter des dépendances, vous pouvez toujours séparer votre couche d'accès aux données et utiliser des méthodes statiques pour renvoyer les données de Dapper.

Lorsque j'utilise Dapper, j'ai généralement une bibliothèque de référentiels qui renvoie de très petits objets ou des listes qui peuvent ensuite être mappées dans un ViewModel et transmises à View (le mappage est effectué par StructureMap, mais peut être géré dans le contrôleur ou un autre assistant). .




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi