3 votes

Modèle de dépôt IRepository<T> dans IServiceRepository

J'ai mis en œuvre le modèle de référentiel et cela fonctionne plutôt bien.

public interface IServiceRepository
{
    User GetUser(int id);
    User GetUser(string email);
    User GetUser(string email, byte[] password);
    //SkipCode
}

//Service repository where I keep extended methods for database manipulation
public class ServiceRepository : IServiceRepository
{
    private readonly IRepository<User> _userRepository;
    private readonly IRepository<Order> _orderRepository;
    private readonly IUnitOfWork _unitOfWork;

    public ServiceRepository(IRepository<User> userRepository, IRepository<Order> orderRepository, IUnitOfWork unitOfWork)
    {
    }

    //SkipImplementation        
}

Lorsque je veux accéder à certaines méthodes de IServiceRepository dans Contrôleur je fais ça

public class AccountController : Controller
{
    private readonly IRepository<OrderDetail> _orderDetailRepository;
    private readonly IRepository<UserDetail> _userDetailRepository;
    private readonly IServiceRepository _serviceRepository;

    public AccountController(IRepository<OrderDetail> orderDetailRepository, IRepository<UserDetail> userDetailRepository, IServiceRepository serviceRepository)
    {
        _orderDetailRepository = orderDetailRepository;
        _userDetailRepository = userDetailRepository;
        _serviceRepository = serviceRepository;
    }
}

Comme vous le voyez, j'injecte IRepositories y IServiceRepository dans ce scénario. Parfois, j'injecte seulement IRepositories o IServiceRepository en fonction des besoins.

La question serait de savoir si je dois déménager tout IRepositories en IServiceRepository . Et dans tous les contrôleurs intégrés seulement IServiceRepository et l'accès IRepositories de IServiceRepository ? Cette mise en œuvre me semble plus claire parce que seuls IServiceRepository sera injecté dans les contrôleurs. Mais pour accéder par exemple à un Repositorie<User> de ServiceRepository devra construire et injecter tous les autres référentiels dans ServiceRepository Cela peut donc ralentir l'ensemble de l'application. Qu'en pensez-vous ?

3voto

oleksii Points 17099

Ma réponse est controversée, alors soyez indulgent avec moi :)

Au point
La construction et l'injection des référentiels devraient prendre presque pas temps. Je suppose que vos dépôts n'ouvrent aucune connexion lorsqu'ils sont créés, donc ne vous souciez pas de la micro-optimisation, faites en sorte que cela fonctionne :)

Vous pouvez fusionner vos interfaces, à condition que l'interface résultante soit de petite taille (disons pas plus d'une dizaine de méthodes), qu'elle soit ciblée et que son objectif soit clair.


Commentaires sur le côté
Quel est le besoin du modèle de référentiel ? Permettez-vous (ou prévoyez-vous dans un avenir proche) de passer facilement d'une base de données à une autre ? Dans la plupart des cas, le référentiel est une surcharge massive et un problème de maintenance.

Considérons ce code

public interface IServiceRepository
{
    User GetUser(int id);
    User GetUser(string email);
    User GetUser(string email, byte[] password);
    //SkipCode
}

Qu'est-ce que ça me dit ? Eh bien, à partir du nom générique, je ne pouvais pas comprendre ce que fait cette interface, c'est comme le service d'un service, l'abstraction sur l'abstraction. Mais d'après les définitions des méthodes, je vois qu'elle fait quelque chose avec User s.

Pourquoi utilisez-vous explicitement IUnitOfWork ? N'est-il pas déjà mis en œuvre par le fournisseur de données que vous utilisez ?

Au lieu de tout cela architecture (bien sûr, si possible), utilisez simplement l'ORM directement, c'est facile à faire et à maintenir, fiable et rapide.

1voto

MattDavey Points 5598

Votre ServiceRepository semble plus proche d'un service de domaine dans une Couche de service qu'un dépôt à part entière.

Un service de domaine coordonne généralement une séquence d'interactions avec divers référentiels de données, par exemple en chargeant un client à partir d'un référentiel de clients et une liste de commandes à partir d'un référentiel de commandes pour présenter une vue unifiée d'un client et de toutes ses commandes. En tant que tels, les services de domaine sont utilisés pour créer une frontière opérationnelle autour d'une application, en abstrayant les différentes séquences d'accès aux données.

C'est une bonne approche, mais je pense que le problème que vous rencontrez est que vous ne l'avez pas poussée assez loin. Si vous décidez que les opérations de l'application doivent être encapsulées dans une série de services de domaine, alors il n'y aura pas besoin d'un contrôleur pour accéder aux référentiels. Si d'un autre côté vous décidez que les contrôleurs prendront cette responsabilité, et accéderont eux-mêmes aux référentiels, alors votre classe ServiceRepository, et d'autres comme elle, deviennent fondamentalement des classes utilitaires.

Je vois que vous avez deux options : améliorer votre couche de service à tel point que les contrôleurs n'ont plus besoin de référentiels :

public class AccountController
{
    public AccountController(IAccountsService service)
    {
        _service = service;
    }

    public void SomeActionMethod(Foo someParams)
    {
        _service.SomeAction(someParams);
    }
}

ou appeler le ServiceRepository ce qu'il est, un utilitaire de raccourci pour faire une séquence fixe d'accès aux données...

public class AccountController
{
    public AccountController(ICustomerRepository customerRepo, IOrderRepository orderRep)
    {
        _customerRepo = customerRepo;
        _orderRepo = orderRepo;
    }

    public void SomeActionMethod(Foo someParams)
    {
        var utility = new CustomerOrderBuilderUtility(_customerRepo, _orderRepo);

        var customerWithOrders = utility.GetCustomerAndOrders(someParams.CustomerId);

        // some domain logic...
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X