Разница между репозиторием и уровнем обслуживания?

В шаблонах проектирования ООП в чем разница между шаблоном репозитория и уровнем обслуживания?

Я работаю над приложением ASP.NET MVC 3, и я пытаюсь понять эти шаблоны проектирования, но мой мозг просто не получает его … еще !!

    Уровень репозитория дает вам дополнительный уровень абстракции при доступе к данным. Вместо написания

    var context = new DatabaseContext(); return CreateObjectQuery().Where(t => t.ID == param).First(); 

    для получения одного элемента из базы данных вы используете интерфейс репозитория

     public interface IRepository { IQueryable List(); bool Create(T item); bool Delete(int id); T Get(int id); bool SaveChanges(); } 

    и вызовите Get(id) . Уровень репозитория предоставляет основные операции CRUD .

    Сервисный уровень предоставляет бизнес-логику, в которой используется repository. Пример сервиса может выглядеть так:

     public interface IUserService { User GetByUserName(string userName); string GetUserNameByEmail(string email); bool EditBasicUserData(User user); User GetUserByID(int id); bool DeleteUser(int id); IQueryable ListUsers(); bool ChangePassword(string userName, string newPassword); bool SendPasswordReminder(string userName); bool RegisterNewUser(RegisterNewUserModel model); } 

    Хотя метод List() репозитория возвращает всех пользователей, ListUsers() IUserService может возвращать только те, к которым пользователь имеет доступ.

    В ASP.NET MVC + EF + SQL SERVER у меня есть этот stream связи:

    Просмотры <- Контроллеры -> Уровень сервиса -> Уровень хранилища -> EF -> SQL Server

    Уровень обслуживания -> Уровень хранилища -> EF. Эта часть работает с моделями.

    Просмотры <- Контроллеры -> Сервисный уровень Эта часть работает с моделями просмотра.

    РЕДАКТИРОВАТЬ:

    Пример streamа для / 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 Orders { get; set; } } 

    Это реализация интерфейса. Он использует classы моделей и repository для создания модели представления:

     public class OrderService : IOrderService { IRepository _clientRepository; public OrderService(IRepository 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 сказал, что repository отвечает за сопоставление ваших данных из формата хранения с вашими бизнес-объектами. Он должен обрабатывать как чтение, так и запись данных (удаление, обновление) с и на хранилище.

    С другой стороны, целью уровня обслуживания является инкапсуляция бизнес-логики в единое целое для содействия повторному использованию кода и разделению проблем. То, что это обычно означает для меня на практике при создании сайтов ASP.NET MVC, заключается в том, что у меня есть эта структура

    [Контроллер] вызывает [Сервис (ы)], который вызывает [repository (ы)]

    Один из принципов, который я нашел полезным, заключается в том, чтобы свести логику к минимуму в controllerах и репозиториях.

    В controllerах это потому, что это помогает мне сушить. Очень распространено, что мне нужно использовать одну и ту же фильтрацию или логику где-то еще, и если я поместил ее в controller, я не смогу ее повторно использовать.

    В репозиториях это потому, что я хочу, чтобы иметь возможность заменить мое хранилище (или ORM), когда что-то лучше приходит. И если у меня есть логика в репозитории, мне нужно переписать эту логику, когда я изменяю repository. Если мой repository возвращает только IQueryable, а служба выполняет фильтрацию, с другой стороны, мне нужно будет только заменить сопоставления.

    Например, недавно я заменил несколько своих репозиториев Linq-To-Sql на EF4, и те, в которых я остался верным этому принципу, могли заменить его в считанные минуты. Там, где у меня была какая-то логика, это заняло несколько часов.

    Обычно repository используется в качестве леса для заполнения ваших сущностей – сервисный уровень выйдет и отправит запрос. Скорее всего, вы разместите repository под своим уровнем обслуживания.

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

    Я взял на себя корпоративное приложение, которое было построено таким образом, и моя первоначальная реакция была WTH ? ViewModels в уровне обслуживания? Я не хотел менять конвенцию, потому что годы развития вошли в нее, поэтому я продолжил возвращать ViewModels. Мальчик превратился в кошмар, когда мы начали использовать WPF. Мы (команда разработчиков) всегда говорили: какой ViewModel? Настоящий (тот, который мы написали для WPF) или один сервис? Они были написаны для веб-приложения и даже имели флаг IsReadOnly, чтобы отключить редактирование в пользовательском интерфейсе. Майор, главный недостаток и все из-за одного слова: ViewModel !!

    Прежде чем совершить ту же ошибку, еще несколько причин в дополнение к моей истории выше:

    Возrotation ViewModel с уровня сервиса огромно, нет. Это как сказать:

    1. Если вы хотите использовать эти сервисы, вам лучше использовать MVVM, а вот ViewModel вам нужно использовать. Ой!

    2. Услуги делают предположение, что они будут отображаться в пользовательском интерфейсе где-нибудь. Что делать, если он используется не-пользовательским интерфейсом, например веб-сервисами или службами Windows?

    3. Это даже не реальная ViewModel. Реальный ViewModel имеет наблюдаемость, команды и т. Д. Это просто POCO с плохим именем. (См. Мою историю выше, почему имена имеют значение.)

    4. Потребляющее приложение лучше будет уровнем представления (ViewModels используются этим слоем), и лучше понять C #. Другой Ой!

    Пожалуйста, не делай этого!

    Давайте будем гением компьютера.