通用存储库和漏洞抽象

时间:2013-12-11 07:09:55

标签: entity-framework entity-framework-5 repository-pattern onion-architecture leaky-abstraction

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

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

是否通用存储库?

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

enter image description here

  • 这种效果如何进行单元测试?我是否仍然可以使用此实现模拟ICustomerRepository

  • 这会如何影响我的持久层?与Azure存储表或NHibernate一样。

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

1 个答案:

答案 0 :(得分:2)

通过坚持模式,你可以拥有一个相对干净的IRepository<T>

数据访问LAyer

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

<强>核心

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

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

所以你可以拥有IQueryable。

  public interface IRepositoryBase<TPoco>{
     IQueryable<TPoco> GetListQ(Expression<Func<TPoco, bool>> predicate);
  //...

如果您决定要添加

,请尝试
 //...
 // logically exposing  IQueryable<T> Include<T>(this IQueryable<T> source, string path) from EF
 IQueryable<TPoco> IncludeNAVProp(string navToInclude);
 }

然后是Repository实现

return  Context.Set<TPoco>().Include(navToInclude);

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

除非你小心,否则EF特定代码。泄漏。 实际上,具有CONCEPT“include”的接口IRepository可以被认为是LEAKY。 将EF细节保留在接口之外是避免泄漏的关键 并且您可以拥有1 IRepository<t>和1 Respository<t>并支持100个表格