【问题标题】:MVC design pattern, service layer purpose?MVC设计模式,服务层目的?
【发布时间】:2015-09-19 18:16:09
【问题描述】:

假设我有以下回购模式:

interface IGenericRepo<T> where T : class
{
     IEnumerable<T> GetAll();
     T GetById(object id);
     void Insert(T obj);
     void Update(T obj);
     void Delete(T obj);
     void Save();
}

interface ICustRepo : IGenericRepo<Cust>
{
     IEnumerable<Cust> GetBadCust();
     IEnumerable<Cust> GetGoodCust();
}

public class CustRepo : ICustRepo<Cust>
{
     //implement method here
}

然后在我的控制器中:

public class CustController
{
     private ICustRepo _custRepo;

     public CustController(ICustRepo custRepo)
     {
         _custRepo = custRepo;
     }

     public ActionResult Index()
     {
         var model = _custRepo.GetAll();
         return View(model);
     }

     public ActionResult BadCust()
     {
         var model = _custRepo.GetBadCust();
         return View(model); 
     }
}

基本上我的模式是这样的

View &lt;-&gt; Controller -&gt; Repo -&gt; EF -&gt; SQL Server

但我看到很多人这样做

View &lt;-&gt; Controller -&gt; Service -&gt; Repo -&gt; EF -&gt; SQL Server

所以我的问题是:

  1. 为什么以及何时需要service layer?不是因为每个非泛型方法都已经在ICustRepo 中实现了,而是添加了另一个不必要的层吗?

  2. 服务层应该返回DTO还是我的ViewModel

  3. 服务层应该与我的 repo 1:1 映射吗?

我已经环顾了几天,但我对答案并不满意。

任何帮助将不胜感激,并为英语不好表示歉意。

谢谢。

更新:

Difference between Repository and Service Layer?

我已经读过了。我已经知道这两者之间的区别,但我想知道为什么和目的。所以这并不能回答我的问题

【问题讨论】:

标签: c# asp.net-mvc entity-framework design-patterns repository


【解决方案1】:

TL;DR

  1. 请参阅下面的说明
  2. 服务层之上的层不应“意识到”服务层之下存在更多层。
  3. 不一定,因为您可以将来自 1 种类型的数据分散在 2 个表中,而“核心”只看到一个,数据访问层负责“分组”并返回服务层类型

说明

典型的 3 层架构由表示层、服务/域层、数据访问层 (DAL) 组成。

将服务层视为应用程序的“核心”。通常,服务层只有将在 DAL 中实现的存储库接口。

因此,它允许您“轻松”切换访问数据的方式。服务层返回的对象不应该是 DAO 的,因为毕竟表示层甚至不“知道” DAL 的存在。

场景: 您有一个 3 层的解决方案。目前拥有所有层没有多大意义。

      /-------------------\
      |      Web App      | <--- Presentation Layer
      |-------------------|
      |  Service Library  | <--- Service Layer
      |-------------------|
      | Entity Framework  | <--- Data Access
      \-------------------/

现在你想在 ASP.NET MVC WebApi 中有一个 REST API

      /--------------------\
      | Web App | REST API | <--- Presentation Layer
      |--------------------|
      |  Service Library   | <--- Service Layer
      |--------------------|
      |  Entity Framework  | <--- Data Access
      \--------------------/

现在,例如,您不再希望使用实体框架作为您的数据访问,而是希望使用 NHibernate。

      /--------------------\
      | Web App | REST API | <--- Presentation Layer
      |--------------------|
      |  Service Library   | <--- Service Layer
      |--------------------|
      |     NHibernate     | <--- Data Access
      \--------------------/

请注意,我们添加了一种新的表示形式并切换了我们访问数据的方式,但服务层从未改变。

通常,服务层会公开要在数据访问层中实现的接口,因此我们可以获得所需的“抽象”。

我在大学里用这种架构实现了一个项目。您可以查看代码HERE

我希望这会有所帮助。对不起,如果我很无聊@解释事情:P

【讨论】:

  • “请注意,我们添加了一种新的表示形式并切换了我们访问数据的方式,但服务层从未改变。”这就是我所需要的。谢谢!
  • 您能否详细说明一下为什么服务层使用接口将自己暴露给客户端?接口似乎通常与实际的服务类是 1:1 匹配的,为什么还要麻烦接口呢?
  • 接口用于数据访问层。例如,您有一个由数据访问实现的 PersonRepository 接口,例如:PersonRepositoryNHibernateRepositoryImpl,您可以配置一个依赖注入容器来注入来自新模块/项目的类。
【解决方案2】:

Ad.1 服务层应该用于整个业务逻辑。更多的是关于单独的职责:

  • Controller - 负责准备viewModel并传递给具体的view,

  • Repository - 负责从 DB 收集实体的抽象层

  • Service - 负责复杂的逻辑。通常情况下,服务使用许多实体来创建一些逻辑并仅返回 DTO。

Ad.2 在我看来,服务层应该返回 DTO 对象,这些对象应该映射到控制器中的视图模型。

Ad.3 不,事实并非如此。在您的示例中,您可以将 GetBadCust 和 GetGoodCust 从 repo 移动到服务并返回一些 DTO

【讨论】:

  • 如果我移动 GetBadCustGetGoodCust 和每个逻辑操作的每个方法,那么 repo 将只包含基本操作,如插入、更新、删除、GetAll。那正确吗?如果是这样的话,你认为我是否可以删除所有 repo 并只保留 Generic?
  • 是的,对我来说这听起来很合理 - 只使用以下方法保留通用 repo:GetAll、GetById、Insert、Update、Delete 和其他更“性感”的方法转移到服务级别。
  • 我不是专家,但是...如果将所有方法从 repo 转移到 service 会发生什么?例如,服务需要 GetGood() 然后从 repo 请求 GetAll(例如 5000 个客户)将转移到您的服务,一旦出现,服务需要丢弃 Bad(例如 4000)并返回 Good(例如 1000)对吗?因此..您的服务到时候变得非常慢。想象一下企业应用程序的数据库中更复杂的查询和更多记录,您需要使用 5、6 个表的内部连接来获取一些值、联合和其他东西。直接在 Repository 中有方法不是更好吗?
猜你喜欢
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
相关资源
最近更新 更多