В шаблонах проектирования ООП в чем разница между шаблоном репозитория и уровнем обслуживания?
Я работаю над приложением ASP.NET MVC 3, и я пытаюсь понять эти шаблоны проектирования, но мой мозг просто не получает его... еще.
В шаблонах проектирования ООП в чем разница между шаблоном репозитория и уровнем обслуживания?
Я работаю над приложением ASP.NET MVC 3, и я пытаюсь понять эти шаблоны проектирования, но мой мозг просто не получает его... еще.
Уровень репозитория дает вам дополнительный уровень абстракции по доступу к данным. Вместо написания
var context = new DatabaseContext();
return CreateObjectQuery<Type>().Where(t => t.ID == param).First();
чтобы получить один элемент из базы данных, вы используете интерфейс репозитория
public interface IRepository<T>
{
IQueryable<T> List();
bool Create(T item);
bool Delete(int id);
T Get(int id);
bool SaveChanges();
}
и вызовите Get(id)
. Уровень репозитория предоставляет основные операции CRUD.
Сервисный уровень предоставляет бизнес-логику, в которой используется репозиторий. Пример службы может выглядеть так:
public interface IUserService
{
User GetByUserName(string userName);
string GetUserNameByEmail(string email);
bool EditBasicUserData(User user);
User GetUserByID(int id);
bool DeleteUser(int id);
IQueryable<User> ListUsers();
bool ChangePassword(string userName, string newPassword);
bool SendPasswordReminder(string userName);
bool RegisterNewUser(RegisterNewUserModel model);
}
В то время как метод репозитория List()
возвращает всех пользователей, ListUsers()
IUserService может возвращать только те, у пользователя есть доступ.
В ASP.NET MVC + EF + SQL SERVER у меня есть этот поток связи:
Виды < - Контроллеры → Уровень сервиса → Уровень хранилища → EF → Сервер SQL
Уровень сервиса → Уровень хранилища → EF. Эта часть работает с моделями.
Виды < - Контроллеры → Сервисный уровень Эта часть работает с моделями просмотра.
EDIT:
Пример потока для /Orders/ByClient/ 5 (мы хотим видеть порядок для конкретного клиента):
public class OrderController
{
private IOrderService _orderService;
public OrderController(IOrderService orderService)
{
_orderService = orderService; // injected by IOC container
}
public ActionResult ByClient(int id)
{
var model = _orderService.GetByClient(id);
return View(model);
}
}
Это интерфейс для обслуживания заказа:
public interface IOrderService
{
OrdersByClientViewModel GetByClient(int id);
}
Этот интерфейс возвращает модель представления:
public class OrdersByClientViewModel
{
CientViewModel Client { get; set; } //instead of ClientView, in simple project EF Client class could be used
IEnumerable<OrderViewModel> Orders { get; set; }
}
Это реализация интерфейса. Он использует классы моделей и репозиторий для создания модели представления:
public class OrderService : IOrderService
{
IRepository<Client> _clientRepository;
public OrderService(IRepository<Client> clientRepository)
{
_clientRepository = clientRepository; //injected
}
public OrdersByClientViewModel GetByClient(int id)
{
return _clientRepository.Get(id).Select(c =>
new OrdersByClientViewModel
{
Cient = new ClientViewModel { ...init with values from c...}
Orders = c.Orders.Select(o => new OrderViewModel { ...init with values from o...}
}
);
}
}
Как сказал Carnotaurus, репозиторий отвечает за сопоставление ваших данных из формата хранения с вашими бизнес-объектами. Он должен обрабатывать как чтение, так и запись данных (удаление, обновление) с и на хранилище.
С другой стороны, целью уровня обслуживания является инкапсуляция бизнес-логики в единое целое для содействия повторному использованию кода и разделению проблем. То, что это обычно означает для меня на практике при создании сайтов ASP.NET MVC, заключается в том, что у меня есть эта структура
[Контроллер] вызывает [Сервис (ы)], который вызывает [репозиторий (ы)]
Один из принципов, который я нашел полезным, заключается в том, чтобы свести логику к минимуму в контроллерах и репозиториях.
В контроллерах это потому, что помогает мне сушить. Очень распространено, что мне нужно использовать одну и ту же фильтрацию или логику где-то в другом месте, и если я поместил ее в контроллер, я не смогу ее повторно использовать.
В репозиториях это потому, что я хочу иметь возможность заменить мое хранилище (или ORM), когда что-то лучше приходит. И если у меня есть логика в репозитории, мне нужно переписать эту логику, когда я изменяю репозиторий. Если мой репозиторий возвращает только IQueryable, а служба выполняет фильтрацию, с другой стороны, мне нужно будет только заменить сопоставления.
Например, недавно я заменил несколько своих репозиториев Linq-To-Sql на EF4, и те, в которых я остался верны этому принципу, могли заменить его в считанные минуты. Там, где у меня была какая-то логика, это заняло несколько часов.
Обычно репозиторий используется в качестве леса для заполнения ваших сущностей - уровень обслуживания будет выходить и запрашивать запрос. Вероятно, вы разместили бы репозиторий под своим уровнем обслуживания.