asp.net-mvc 存储库和服务层之间的区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5049363/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between Repository and Service Layer?
提问by Sam
In OOP Design Patterns, what is the difference between the Repository Pattern and a Service Layer?
在 OOP 设计模式中,存储库模式和服务层有什么区别?
I am working on an ASP.NET MVC 3 app, and am trying to understand these design patterns, but my brain is just not getting it...yet!!
我正在开发一个 ASP.NET MVC 3 应用程序,并试图理解这些设计模式,但我的大脑还没有明白......
回答by LukLed
Repository Layer gives you additional level of abstraction over data access. Instead of writing
存储库层为您提供了对数据访问的额外抽象级别。而不是写作
var context = new DatabaseContext();
return CreateObjectQuery<Type>().Where(t => t.ID == param).First();
to get a single item from database, you use repository interface
要从数据库中获取单个项目,请使用存储库接口
public interface IRepository<T>
{
IQueryable<T> List();
bool Create(T item);
bool Delete(int id);
T Get(int id);
bool SaveChanges();
}
and call Get(id)
. Repository layer exposes basic CRUDoperations.
并调用Get(id)
。存储库层公开基本的CRUD操作。
Service layer exposes business logic, which uses repository. Example service could look like:
服务层暴露业务逻辑,使用存储库。示例服务可能如下所示:
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);
}
While List()
method of repository returns all users, ListUsers()
of IUserService could return only ones, user has access to.
虽然List()
repository 的方法返回所有用户,但ListUsers()
IUserService 只能返回一个,用户有权访问。
In ASP.NET MVC + EF + SQL SERVER, I have this flow of communication:
在 ASP.NET MVC + EF + SQL SERVER 中,我有这样的通信流程:
Views <- Controllers -> Service layer -> Repository layer -> EF -> SQL Server
Service layer -> Repository layer -> EFThis part operates on models.
Views <- Controllers -> Service layerThis part operates on view models.
视图<-控制器->服务层->存储库层->EF->SQL Server
Service layer -> Repository layer -> EF这部分对模型进行操作。
Views <- Controllers -> Service layer这部分对视图模型进行操作。
EDIT:
编辑:
Example of flow for /Orders/ByClient/5 (we want to see order for specific client):
/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);
}
}
This is interface for order service:
这是订单服务的接口:
public interface IOrderService
{
OrdersByClientViewModel GetByClient(int id);
}
This interface returns view model:
此接口返回视图模型:
public class OrdersByClientViewModel
{
CientViewModel Client { get; set; } //instead of ClientView, in simple project EF Client class could be used
IEnumerable<OrderViewModel> Orders { get; set; }
}
This is interface implementation. It uses model classes and repository to create view model:
这是接口实现。它使用模型类和存储库来创建视图模型:
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...}
}
);
}
}
回答by Mikael Eliasson
As Carnotaurus said the repository is responsible for mapping your data from the storage format to you business objects. It should handle both how to read and write data(delete, update too) from and to the storage.
正如 Carnotaurus 所说,存储库负责将您的数据从存储格式映射到您的业务对象。它应该处理如何从存储读取和写入数据(删除,更新)。
The purpose of service layer on the other hand is to encapsulate business logic into a single place to promote code reuse and separations of concerns. What this typically means for me in practice when building Asp.net MVC sites is that I have this structure
另一方面,服务层的目的是将业务逻辑封装到一个地方,以促进代码重用和关注点分离。在构建 Asp.net MVC 站点时,这在实践中对我来说通常意味着我有这种结构
[Controller] calls [Service(s)] who calls [repository(ies)]
[Controller] 调用 [Service(s)] 调用 [repository(ies)]
One principle I have found useful is to keep logic to a minimum in controllers and repositories.
我发现有用的一个原则是将控制器和存储库中的逻辑保持在最低限度。
In controllers it is because it helps keeping me DRY. It's very common that I need to use the same filtering or logic somewhere else and if I placed it in the controller I can't reuse it.
在控制器中,这是因为它有助于让我保持干爽。我需要在其他地方使用相同的过滤或逻辑是很常见的,如果我把它放在控制器中,我就不能重用它。
In repositories it is because I want to be able to replace my storage(or ORM) when something better comes along. And if I have logic in the repository I need to rewrite this logic when I change the repository. If my repository only returns IQueryable and the service does the filtering on the other hand, I will only need to replace the mappings.
在存储库中,这是因为我希望能够在出现更好的东西时替换我的存储(或 ORM)。如果我在存储库中有逻辑,我需要在更改存储库时重写此逻辑。如果我的存储库只返回 IQueryable 并且另一方面服务进行过滤,我只需要替换映射。
For example I recently replaced several of my Linq-To-Sql repositories with EF4 and those where I had stayed true to this principle could replaced in a matter of minutes. Where I had some logic it was a matter of hours instead.
例如,我最近用 EF4 替换了我的几个 Linq-To-Sql 存储库,而那些我坚持这一原则的存储库可以在几分钟内替换掉。在我有一些逻辑的地方,它只是几个小时的问题。
回答by CodingYoshi
The accepted answer (and upvoted hundreds of time) has a major flaw. I wanted to point this out in the comment but it will just get buried down there in 30 something comments so pointing out here.
接受的答案(并被数百次投票)有一个重大缺陷。我想在评论中指出这一点,但它只会被埋在 30 条评论中,所以在这里指出。
I took over an enterprise application which was built that way and my initial reaction was WTH? ViewModels in service layer? I did not want to change the convention because years of development had gone into it so I continued with returning ViewModels. Boy it turned into a nightmare when we started using WPF. We (the team of devs) were always saying: which ViewModel? The real one (the one we wrote for the WPF) or the services one? They were written for a web application and even had IsReadOnlyflag to disable edit in the UI. Major, major flaw and all because of one word: ViewModel!!
我接手了一个以这种方式构建的企业应用程序,我最初的反应是WTH?服务层中的视图模型?我不想改变约定,因为已经进行了多年的开发,所以我继续返回 ViewModel。当我们开始使用 WPF 时,它变成了一场噩梦。我们(开发团队)总是在说:哪个 ViewModel?真正的(我们为 WPF 编写的)还是服务?它们是为 Web 应用程序编写的,甚至有IsReadOnly标志来禁用 UI 中的编辑。主要的,主要的缺陷,全都因为一个词:ViewModel!!
Before you make the same mistake, here are some more reasons in addition to my story above:
在你犯同样的错误之前,除了我上面的故事之外,还有一些原因:
Returning a ViewModel from the service layer is a huge no no. That's like saying:
从服务层返回一个 ViewModel 是一个巨大的禁忌。这就像在说:
If you want to use these services you better be using MVVM and here is the ViewModel you need to use. Ouch!
The services are making the assumption they will be displayed in a UI somewhere. What if it is used by a non UI application such as web services or windows services?
That is not even a real ViewModel. A real ViewModel has observability, commands etc. That is just a POCO with a bad name. (See my story above for why names matter.)
The consuming application better be a presentation layer (ViewModels are used by this layer) and it better understand C#. Another Ouch!
如果您想使用这些服务,您最好使用 MVVM,这里是您需要使用的 ViewModel。哎哟!
这些服务假设它们将显示在某个 UI 中。如果它被非 UI 应用程序(例如 Web 服务或 Windows 服务)使用怎么办?
那甚至不是真正的 ViewModel。一个真正的 ViewModel 具有可观察性、命令等。那只是一个名字不好的 POCO。(有关为什么名称很重要,请参阅我上面的故事。)
消费应用程序最好是一个表示层(该层使用 ViewModels)并且它更好地理解 C#。另一个哎哟!
Please, don't do that!
请不要那样做!
回答by CarneyCode
Usually a repository is used as scaffolding to populate your entities - a service layer would go out and source a request. It is likely that you would put a repository under your service layer.
通常,存储库用作脚手架来填充您的实体 - 服务层将出去并发出请求。您很可能会将存储库放在服务层下。
回答by Akshay
Repository layer is implemented to access the database and helps to extend the CRUD operations on the database. Whereas a service layer consists of the business logic of the application and may use the repository layer to implement certain logic involving the database. In an application, it is better to have a separate repository layer and service layer. Having separate repository and service layers make the code more modular and decouple the database from business logic.
Repository 层用于访问数据库并帮助扩展对数据库的 CRUD 操作。而服务层由应用程序的业务逻辑组成,并且可以使用存储库层来实现涉及数据库的某些逻辑。在一个应用程序中,最好有一个单独的存储库层和服务层。拥有单独的存储库和服务层使代码更加模块化并使数据库与业务逻辑分离。