通用存储库和漏洞抽象

Dav*_*New 5 entity-framework leaky-abstraction repository-pattern onion-architecture entity-framework-5

我正在实现一个存储库模式.我的主要原因是:

  • 从持久性细节中抽象客户端代码(实体框架)
  • 支持可测试性

通用存储库与否?

我遇到的问题是我是否应该有一个通用的存储库.一种IQueryable<T> Query()方法将为调用代码提供构造特定查询的手段.这里的问题是这是漏洞抽象 - 实体框架细节现在泄漏到我的客户端代码中.

在此输入图像描述

  • 这种影响单元测试怎么样? 我还能ICustomerRepository用这个实现模拟吗?

  • 这种效果如何影响我的持久层?像Azure存储表或NHibernate.

否则我将不得不实现非常具体的查询方法ICustomerRepository,例如GetIsActiveByFirstName()GetIsActiveByDistrict().我不喜欢这个,因为我的存储库类将变得拥挤不同的查询方法.该系统有数百种型号,因此可以有数百甚至数千种这样的方法来编写和维护.

phi*_*ady 3

IRepository<T>坚持图案就可以得到相对干净的效果。

数据访问层

  • 参考 EF 和 Core 项目
  • Respository<T> : IRepository<T>
  • 选项具有 IEFJunk 声明(仅当使用多个存储库时)
  • 参考核心
  • 存储库注入上下文(通常在实例化期间)

  • 可以“注入”的接口
  • IRepository 声明。不使用 EF 数据类型。
  • 没有提及 EF

所以现在 Core 中的代码您可以参考IRepository<t>. 实现类可以具有 EF 细节。但这不能从核心访问!

这样你就可以拥有 IQueryable 了。

  public interface IRepositoryBase<TPoco>{
     IQueryable<TPoco> GetListQ(Expression<Func<TPoco, bool>> predicate);
  //...
Run Code Online (Sandbox Code Playgroud)

但是如果您决定要添加

 //...
 // logically exposing  IQueryable<T> Include<T>(this IQueryable<T> source, string path) from EF
 IQueryable<TPoco> IncludeNAVProp(string navToInclude);
 }
Run Code Online (Sandbox Code Playgroud)

然后是存储库实现

return  Context.Set<TPoco>().Include(navToInclude);
Run Code Online (Sandbox Code Playgroud)

要求底层提供者是 EF。所以现在嘲笑是针对实际的 EF 提供者的。

除非你很小心,否则 EF 特定代码。泄漏出来。事实上,具有“include”概念的接口 IRepository 已经可以被认为是泄漏的。将 EF 细节排除在接口之外是避免泄漏的关键。
可以有 1IRepository<t>和 1Respository<t>并支持 100 个表