4

让我们从总结这个问题的两句话开始:“包装 DbContext 是一个泄漏的抽象。无论如何,您最终会在服务/控制器层中对 EF 产生某种依赖。” 引用 ref 和第二个引用:

“DbContext 类

表示工作单元和存储库模式的组合,使您能够查询数据库并将更改组合在一起,然后将这些更改作为一个单元写回存储。” MSDN

请不要说存储库模式允许您简单地换出数据库,它不允许。有没有人用成熟的应用程序做到这一点?也请不要回答存储库模式不应该公开 IQueryable,我认为这只是另一种表示您不信任与您一起工作的人的方式。

我完全支持封装、代码覆盖率/可测试性,但由于这种流行的 EF 回购模式暴露了 IQueryable,因此不再需要这种模式:

   public interface IRepository<T> where T : class
    {
    IQueryable<T> GetAll();
    T GetById(int id);
    IEnumerable<T> Get(Expression<Func<T, bool>> filter = null,Func<IQueryable<T>,IOrderedQueryable<T>> orderBy = null, string includeProperties = "");
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
    void Delete(int id);
}

存储库模式与 UOW 模式相结合的唯一好处是: 1. 轻松启用依赖注入模式以提高可测试性/代码覆盖率 2. 封装外部集成存在的复杂性(对不同供应商的 Web 服务调用、Web API、数据库, ETC..)

那么我得到了什么封装,我没有通过使用 MyDbContext 得到什么:DbContext 类?我的 ORM 是抽象的 当然,我通过工作的 UOW 和常见的查询(如添加和删除)获得了一些控制器的一致性,但这真的值得付出努力。我不能只相信我的开发人员是统一的,当他们以自己的方式做事时,不要让强迫症。并且由于控制器可以编写它想要的任何查询,这难道不是面对单元测试吗?并且(甚至更大的上限大声笑)如果我要调用第三方 API,我可以在控制器的 MyDbContext 类中使其可访问,因此它看起来只是对控制器的另一个数据调用。

我再说一遍,为什么不直接使用 ORM,它是数据抽象!

以下是一些反对存储库模式的论据:

http://ayende.com/blog/4784/architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer

http://ayende.com/blog/3955/repository-is-the-new-singleton

http://lostechies.com/jimmybogard/2012/09/20/limiting-your-abstractions/

http://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/

这是存储库模式的正确论据(虽然不够令人信服): http: //www.sapiensworks.com/blog/post/2012/10/10/Do-We-Need-The-Repository-Pattern.aspx

4

2 回答 2

6

如果我再看到 Ayende 的帖子,我想我会发疯的。让我们慢慢来:

  1. 通用存储库的适用性有限。就个人而言,我仅将它用于域存储库,并且仅在我以序列化形式存储聚合根时使用。对于其余的事情(阅读:查看模型、报告),我将有一个存储库,专为满足需要这些模型的层的需求而设计。

  2. IQueryable 几乎是一个查询生成器。您不告诉存储库如何构建某些东西(IQUeryable),您只是从中询问一些东西。如果您使用的是 IQueryable,那么您已经完成了存储库工作的一部分(破坏了更高层的 SRP)。同样暴露 IQueryable 意味着高层必须知道用于创建查询的 pocos/entities。如果您的老板决定从现在开始您将从 Web 服务中获取数据,那么您将如何处理所有散布在各处的 IQueryable 和 ORM 实体?还是 RDBMS 太慢了,所以让我们使用 Document Db?是的,它可能支持 linq,但你确定你会定义相同的实体吗?

  3. 不要相信你的开发者。相信一个适当的架构,一个你不混合层职责并且尊重 SRP(单一职责原则)的架构。如果您正在设计,假设视图模型是根据数据在 db 中的存储方式而不是根据您在视图中的需要,那么您将遇到紧密耦合问题。

  4. 因为不需要更改 ORM 或存储技术而不使用 repo 的原因是恕我直言,原因类似于:为什么使用 DI 容器或接口,这些类很有可能会改变,我们可以手动进行反正注射。

  5. 使用存储库意味着您不必关心如何以及从何处检索模型。存储库公开了业务友好的语义 (GetTopSellingProducts)。使用 orm,您必须构建查询(每个人都喜欢在 linq 中进行连接和子查询),了解实体,进行投影等。为什么更高层要关心这些细节?这是“问,不说如何”的原则 (j/k)

毕竟,这都是关于可维护代码的,我希望我的代码易于理解。

于 2013-01-26T08:11:20.720 回答
3

我再说一遍,为什么不直接使用 ORM,它是数据抽象!

它是数据抽象而不是数据抽象。

如果您需要将其切换出来,它是关于抽象您的 ORM。不是关于通用回购可以直接通过 DbContext 提供什么好东西。如果您确实需要切换 EF 和 DbContext 并且它是高度耦合的,您将需要编辑使用 DbContext 的代码的所有部分,或者被迫在您切换到的任何 ORM 上实现 DbContext 接口。

在说我认为在大多数应用程序中切换 ORM 的可能性很小,并且直接使用 DbContext 的便利性超过了耦合到 EF 的风险。但是,我仍然明白为什么有些人会根据应用程序要求和寿命来这样做。

于 2013-01-25T23:23:04.620 回答