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