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

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

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

5 ответов


слой репозитория дает вам дополнительный уровень абстракции над доступом к данным. Вместо того чтобы писать!--11-->

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). Слой репозитория предоставляет basic 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 может возвращать только те, к которым пользователь имеет доступ.

In ASP.NET MVC + EF + SQL SERVER, у меня есть этот поток связи:

вид сервис слой -> репозитории слой -> эф -> 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...}     
             }
         );
     }
}

Как карнотавр сказал репозиторий отвечает за отображение данных из формата хранения в бизнес-объекты. Он должен обрабатывать как чтение, так и запись данных(удаление, обновление) из и в хранилище.

цель сервисного уровня, с другой стороны, заключается в инкапсуляции бизнес-логики в одном месте для содействия повторному использованию кода и разделению проблем. Что это обычно означает для меня на практике при строительстве Asp.net сайты MVC - это то, что у меня есть структура

[контроллер] вызывает [сервис(Ы)], который вызывает [репозиторий(ы)]

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

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

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

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


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


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

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

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

возврат ViewModel из уровня сервиса является огромным no no. Это как сказать:

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

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

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

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

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


слой репозитория реализован для доступа к базе данных и помогает расширить операции CRUD в базе данных. В то время как уровень сервиса состоит из бизнес-логики приложения и может использовать уровень репозитория для реализации определенной логики, связанной с базой данных. В приложении лучше иметь отдельный слой репозитория и слой сервиса. Наличие отдельных слоев репозитория и сервиса делает код более модульным и отделяет базу данных от бизнес-логики.