Шаблон репозитория 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...
}
}