Шаблон репозитория IRepository<T> внутри IServiceRepository

Я реализовал шаблон репозитория, и он работает довольно хорошо.

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        
}

Когда я хочу получить доступ к некоторым методам из IServiceRepository в контроллере я делаю это

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

Как видите, я делаю инъекцию IRepositories а также IServiceRepository в этом сценарии. Иногда я только вводить IRepositories или же IServiceRepository в зависимости от потребностей.

Вопрос был бы, может быть, я должен переместить все IRepositories в IServiceRepository, И во все контроллеры встраивать только IServiceRepository и доступ IRepositories от IServiceRepository? Эта реализация выглядит более понятной для меня, потому что только IServiceRepository будет введен в контроллеры. Но для доступа, например, один Repositorie<User> от ServiceRepository нужно будет построить и внедрить все остальные репозитории в ServiceRepository, так что это может замедлить все приложение. Как вы думаете?

2 ответа

Решение

Мой ответ противоречив, поэтому, пожалуйста, потерпите меня:)

К точке
Создание и внедрение репозиториев должно занимать почти не время. Я предполагаю, что ваши репозитории не открывают никаких соединений при их создании, так что не беспокойтесь о микрооптимизации, просто сделайте так, чтобы она работала:)

Вы можете объединять свои интерфейсы, если конечный интерфейс небольшой (скажем, не более 10 методов), сфокусирован и имеет четкую цель.


Дополнительные комментарии
Зачем нужен шаблон хранилища? Вы разрешаете (или в ближайшем будущем) легко переключаться между базами данных? В большинстве случаев хранилище - это массовое излишнее количество ресурсов и проблема обслуживания.

Рассмотрим этот код

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

Что это говорит мне? Ну, из общего названия я не мог понять, что делает этот интерфейс, это как сервис сервиса, абстракция над абстракцией. Но из определения метода я вижу, что он что-то делает с User s.

Почему вы явно используете IUnitOfWork? Разве это не реализовано поставщиком данных, который вы используете?

Вместо всей этой архитектуры (конечно, если это возможно), просто используйте ORM напрямую, это легко сделать и поддерживать, надежно и быстро.

Ваш ServiceRepository, похоже, ближе к доменной службе на уровне сервиса, чем к собственному репозиторию.

Служба домена обычно координирует последовательность взаимодействий с различными хранилищами данных, например, загружая клиента из хранилища клиентов и список заказов из хранилища заказов, чтобы представить единое представление о клиенте и всех его заказах. Как таковые доменные службы используются для создания операционной границы вокруг приложения - абстрагирование различных последовательностей доступа к данным.

Это хороший подход, но я думаю, что проблема у вас в том, что вы не зашли достаточно далеко. Если вы решите, что операции приложения должны быть инкапсулированы в серию доменных служб, контроллеру не потребуется доступ к репозиториям. Если, с другой стороны, вы решите, что контроллеры возьмут это хранилище и получат доступ к самим репозиториям, то ваш класс ServiceRepository и другие подобные ему в основном станут служебными классами.

Я вижу, что у вас есть два варианта - улучшить свой уровень обслуживания до такой степени, что контролерам больше не нужны репозитории:

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

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

или вызвать ServiceRepository, что это такое, ярлык для выполнения фиксированной последовательности доступа к данным...

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...
    }
}
Другие вопросы по тегам