【问题标题】:Generic Repository and Leaky Abstraction通用存储库和泄漏抽象
【发布时间】:2013-12-11 19:18:35
【问题描述】:

我正在实施存储库模式。我这样做的主要原因:

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

是否有通用存储库?

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

  • 这将如何影响单元测试?我是否仍然能够使用此实现模拟ICustomerRepository

  • 替换我的持久层会产生什么影响? 就像 Azure 存储表或 NHibernate。

否则我将不得不在ICustomerRepository 上实现非常具体的查询方法,例如GetIsActiveByFirstName()GetIsActiveByDistrict()。我非常不喜欢这个,因为我的存储库类将挤满不同的查询方法。这个系统有数百个模型,因此可能有数百甚至数千个这样的方法需要编写和维护。

【问题讨论】:

  • 感谢您的链接,但我仍然对测试有点不清楚。为什么我不能用 IQueryable 模拟?
  • 您可以使用 IQueryable 模拟/起订量。 msdn.microsoft.com/en-us/data/dn314429 ... Gert 链接的点有链接,除非您对如何声明 IREPOSITORY 非常了解,并且最终可能会泄露 EF 细节。模拟 EF 并不简单,但是您应该声明 IRrespository 的域/核心层应该没有对 EF 的引用。
  • 哦,我还写了this关于嘲笑。我没办法……

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


【解决方案1】:

坚持模式,你可以拥有一个相对干净的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);
  //...

但是如果你决定要添加

 //...
 // 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 特定代码。泄漏出来。 事实上,具有概念“包含”的接口 IRepository 已经可以被认为是 LEAKY。 将 EF 细节排除在接口之外,是避免泄漏的关键。
您可以拥有 1 个IRepository&lt;t&gt; 和 1 个Respository&lt;t&gt; 并支持 100 多个表

【讨论】:

    猜你喜欢
    • 2011-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多