为服务层设计DI(构造函数注入)的存储库

时间:2011-11-07 04:52:50

标签: asp.net-mvc entity-framework dependency-injection repository inversion-of-control

我正在构建一个MVC3应用程序,尝试使用IoC和构造函数注入。我的数据库(到目前为止)大约有50个表。我正在使用EF4(带有POCO T4模板)作为我的DAC代码。我正在使用存储库模式,每个表都有自己的存储库。我的服务层中的服务类是使用这些存储库注入的。

问题:我的服务类的数量正在增加所需的存储库数量。在某些情况下,我正在接近10个存储库,它开始闻起来。

是否有一种设计存储库和服务类的通用方法,使服务不需要这么多的存储库?

以下是我的想法,我不确定哪一个是对的:

1)这是一个标志,我应该考虑将我的存储库组合/分组到表的相关部分,减少每个服务类的数量或依赖存储库。但是,这种方法的问题在于它会使我的存储库膨胀并使其复杂化,并使我无法使用所有存储库的通用接口(数据检索/更新的标准方法)。

2)这是一个标志我应该考虑根据我的存储库(表)将我的服务分成组。问题在于我的一些服务方法共享通用实现,并且跨类破坏这些可能会使我的依赖性变得复杂。

3)这表明我不知道自己在做什么,并且有一些我根本无法看到的根本错误。

更新:有关我如何实施EF4和存储库的想法,请查看codeplex上的this sample app(我使用version 1)。然而,看看那里(和这里)的一些评论,看起来我需要做更多的阅读以确保这是我想要的路线 - 听起来可能不是。

4 个答案:

答案 0 :(得分:6)

如果你看一下DDD Aggregate Root模式并尝试在这个视角中看到你的数据,你会发现许多表根本没有独立的存在。他们的数据仅在其父母的背景下有效。它们上的大多数操作都要求您获得父项。如果您可以对这些表进行分组并找到父实体\ repository,则可以删除所有其他子存储库。将父级子项关联起来的复杂性(假设您使用独立仓库检索父级和子级)不会转移到DAL中 重构服务接口也是一个可行的选择,任何常用功能都可以移动到基类中,或者可以将其自身定义为所有现有服务所使用的服务(Is A vs Has A)

答案 1 :(得分:6)

Chandermani is right您的某些表可能不是核心域类。这意味着除了单一类型的父实体之外,您永远不会搜索该数据。在这些情况下,您可以将它们称为“复杂类型”而不是完整的实体,EF仍然会照顾您。

  

我正在使用存储库模式,每个表都有自己的存储库

我希望你不是从头开始写这些。

EF 4.1已经实现了the Repository PatternDbSet)和the Unit of Work patternDbContext)。旧版本也可以,但可以通过将DbContext模板更改为IDbSet来轻松调整FindById模板以提供干净的可模拟实现。

我已经看过一些教程文章,人们仍然会写自己的文章。这对我来说很奇怪,因为除了他们“正在实施存储库模式”之外,他们通常不会提供理由。

Linq之类的访问方法编写这些存储库的包装器使其更容易访问,但正如您所看到的那样,大量的工作可能几乎没有回报。就个人而言,除非我发现要封装有趣的域逻辑或复杂查询,否则我甚至不会费心直接使用IDbSet来对抗DbContext

  

我的服务层中的服务类是使用这些存储库注入的。

即使您选择使用自定义查询包装器,您也可以选择简单地注入{{1}},并让服务代码实例化它所需的包装器。您仍然可以模拟数据访问层,您将无法模拟包装器代码。我仍然建议你注入不那么通用的,因为复杂的实现正是你希望能够在维护中分解出来的东西,或者用模拟代替。

答案 2 :(得分:1)

@Chandermani对聚合根有一个好处。存储库不应该与表格进行1:1映射。

注入大量依赖项是您的服务做得太多的一个好兆头。遵循单一责任原则,并将它们重构为更易于管理的部分。

答案 3 :(得分:0)

您的服务是否写入所有存储库?我发现我的服务与存储库紧密相关,它们围绕存储库公开的CRUD操作提供业务逻辑。

相关问题