5

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

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

通用存储库与否?

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

在此处输入图像描述

  • 这将如何影响单元测试? 我还能ICustomerRepository用这个实现来模拟吗?

  • 这种效果会如何替换我的持久层?像 Azure 存储表或 NHibernate。

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

4

1 回答 1

3

你可以有一个相对干净IRepository<T>的坚持模式。

数据访问层

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

  • 可以“注入”的接口
  • 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);
 }

然后是存储库实现

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

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

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

于 2013-12-11T11:06:57.663 回答