我一直在阅读关于存储库模式和服务层的角色,我(我认为)很清楚这两者之间的区别。但是一个简单的问题让我头疼了一段时间。
我知道数据访问层如何负责...访问数据,因此典型的存储库可能有插入,更新,删除和保存等方法(基本的CRUD方法)。服务层包含所有业务内容,验证,发送电子邮件和所有爵士乐,我读过的一件事是服务层不应重复存储库方法,因为此设置不会添加任何值。< / p>
但我的问题是'添加'方法。假设我有供应商类,我想在供应商列表中添加特定供应商。用户通过UI(MVC Web应用程序)输入供应商信息,并调用Create
控制器方法。
现在控制器应该怎样处理才能坚持这个供应商?
由于纯存储库实现除了持久化实体之外不会做任何其他事情,如果我有一些验证和/或业务规则,我应该明显使用服务层。但是,如果我不这样做,控制器应该直接处理存储库?在我看来,这似乎打破了架构的分层性质。控制器正在跳过服务层并与持久层进行通信。
假设我想要安全并使用服务层(因为我可能有验证和其他与供应商打交道相关的东西)。我最终会:
这是我从一开始就不想要的,因为我现在有一个1对1的方法映射服务层和数据访问层。
所以我的问题是:(添加|更新|删除)供应商方法应该去哪里?
此外,是否可以绕过服务层并直接从控制器与存储库层对话?
答案 0 :(得分:2)
我不认为你的问题有一个明确的答案,因为有很多因素要考虑(正如你所指出的那样,这也是一个悖论)。我相信最好的实现有一些重要的部分。
一个非常通用的存储库,它与数据源交互并执行插入,更新,删除基本的CRUD方法(正如您所指出的那样)。最好这将以通用方式完成,以便您的应用程序中的交互一致。例如,返回单个实体的方法,如T Single(Func<T, bool> where)
。
包含封装业务功能的方法的特定业务服务。这些服务是唯一允许与存储库交互的服务。除了'Hello World'样式示例之外,这些方法不会简单地添加或删除项目,但它们可能与2个或更多实体交互并执行复杂的业务逻辑。例如,服务方法可能是“CreateAccount”或“RemmoveBlogPost”,毫无疑问,这不仅仅需要添加单个实体或删除一个实体。
'瘦'和'哑'控制器几乎不执行任何逻辑,只是根据需要调用服务方法。控制器只是消耗变量并返回响应。但是,他们可能会在每个控制器操作中调用各种服务方法。服务方法的混合和重用可以实现高效的DRY编码实践。
当您意识到要在应用的其他部分执行某种方法的全部或部分时,此方法会显示其强度。例如,如果您正在构建一个博客应用程序,您可能会发现应用程序的面向公众需要一种方法来查看单个博客帖子,管理员方面也需要它。在这个简单的示例中,将在每个控制器中重复按Id返回博客帖子,但是,如果您创建了一个名为getBlogPostById的服务方法,则可以在两个控制器中重用逻辑。