通用知识库与 EF 4.1什么是点

当我深入研究 DbContext、 DbSet 和相关接口时,我想知道为什么需要围绕这些实现实现一个单独的“ Generic”Repository?

看起来 DbContext 和 IDbSet 完成了您需要的所有工作,并在 DbContext 中包含了“工作单元”。

我是不是遗漏了什么,或者人们似乎喜欢无缘无故地增加另一层依赖。

28690 次浏览

你说得对。DbContext是工作单元模式的实现,而 IDbSet是存储库模式的实现。

目前,存储库非常流行并且被过度使用。每个人都使用它们,只是因为有几十篇关于为实体框架创建存储库的文章,但是没有人真正描述与这个决策相关的挑战。

使用存储库的主要原因通常是:

  • 从上层隐藏 EF
  • 使代码更易于测试

第一个原因是某种建筑的纯粹性和伟大的想法,如果你让你的上层独立于 EF,你可以在以后切换到其他持久化框架。你在现实世界中见过多少次这样的东西?这个原因使得使用 EF 变得更加困难,因为存储库必须公开许多额外的特性,这些特性包含了 EF 默认允许的内容。

同时,包装 EF 代码可以使您的代码组织得更好,并遵循关注点分离规则。对我来说,这可能是存储库和工作单元的唯一真正优势,但你必须明白,遵循这个规则与 EF 可能会使您的代码更好地维护和更好的可读性,但在最初的努力,创建您的应用程序将高得多,对于较小的应用程序,这可能是不必要的复杂性。

第二个理由在一定程度上是正确的。EF 的最大缺点是严格的架构,很难被嘲笑,所以如果你想要单元测试上层,你必须包装 EF,以某种方式允许嘲笑它的实现。但是,这有许多其他后果,我描述了 给你

我跟随 Ayende 的博客。如果你曾经使用过 NHibernate,你可能知道他的文章。这个人最近写了几篇反对使用 NHibernate 存储库的文章,但是 NHibernate 更加可笑。

我挣扎在同样的问题,和模仿 EF 层的单元测试是重要的。但是我偶然读到一篇很棒的文章,它解释了如何通过确保派生的 DbContext 实现通用接口并公开 IDbSet 而不是 DbSet 来设置 EF 4.1 DbContext。由于我使用 Database First 方法,因为我们的数据库已经存在,所以我只是修改了用于生成派生的 DbContext 的 T4模板,以生成它来返回 IDbSet 接口,以及从我的通用接口派生。这样就可以很容易地对整个事情进行模拟,而且不需要实现自己的工作单元或存储库模式。只需编写服务代码来使用通用接口,当您进行单元测试时,只需使用特定的测试数据模拟通用接口,就可以了。

Http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/

创建存储库的一个原因是,如果决定从 EntityFramework 转移到其他框架,或者从 EntityFramework 转移到其他框架,则可以隐藏 DBSet 和 DbContext 的实现。

例如,我正在使用 NHibernate,并将对该框架的所有调用封装在我的存储库类中。它们返回 IEnumable,因为它们的 get 是“通用的”,并且我的存储库具有标准的 CRUD 操作(更新、删除等)。我已经搬到实体框架很久了。在这样做之后,我不需要更改 ViewModel 类或其他类中的任何内容,因为它们指向我的存储库——我只需要更改存储库的内部。这使得迁徙时的生活更加轻松。

(我使用 NHibernate 是因为我们连接到 ISeries,当时没有使用 EF 和 ISeries 的成本效益实现。唯一可用的方法是向 IBM 支付12,000美元购买 DB2Connect)