Разница между репозиторием и уровнем сервиса?
в шаблонах проектирования ООП, в чем разница между шаблоном репозитория и слоем сервиса?
Я работаю над 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. Это как сказать:
Если вы хотите использовать эти службы, вам лучше использовать MVVM, и вот ViewModel, который вам нужно использовать. Оуч!
сервис делает предположение, что они будут отображаться в пользовательском интерфейсе где-то. Что делать, если он используется не UI-приложением, таким как веб-службы или windows услуги?
Это даже не настоящая ViewModel. реальная ViewModel имеет наблюдаемость, команды и т. д. Это просто поко с плохой репутацией. (См. мою историю выше, Почему имена имеют значение.)
потребляющее приложение лучше быть слоем презентации (ViewModels используются этим слоем), и он лучше понимает C#. Еще Один Ой!
пожалуйста, не делай этого!
слой репозитория реализован для доступа к базе данных и помогает расширить операции CRUD в базе данных. В то время как уровень сервиса состоит из бизнес-логики приложения и может использовать уровень репозитория для реализации определенной логики, связанной с базой данных. В приложении лучше иметь отдельный слой репозитория и слой сервиса. Наличие отдельных слоев репозитория и сервиса делает код более модульным и отделяет базу данных от бизнес-логики.