轻松实现存储库模式

Easy implementation of Repository Pattern

我直接在 MVC 5 中使用 ADO.NET 而不是 Entity Framework。

我指的是这个 example 来实现存储库模式。

存储库模式的简单实现:

  1. 我会创建一个模型
  2. 我将创建一个带有 CRUD 方法声明的接口
  3. 我将在数据访问层中创建一个 class,它将实现上述接口并实现 CRUD 方法

我想知道为什么要使用Interface?我可以不按照上面的第 (3) 点直接使用 class 吗?

接口的作用是什么?

从以上三点来看,是不是Repository Pattern的正确实现?

在设计良好的代码中,您必须使用接口,而不是实现。它有好处。假设您有一个 class 和一个代码片段:

IBookRepository bookRepository;

public Book GetInterestingBook() {
  var book = bookRepository.getBooks().FirstOrDefault(x => x.IsInteresting);
  return book;
}

现在我将向您展示一些好处:

  1. 使用接口允许您通过依赖注入隐式创建 bookRepository 实例(Ninject、Unity 等。它们有很多)。如果您决定将存储库实现从 Entity Framework 更改为 NHibernate,则无需更改代码。只需更改映射文件中的映射以用于 IBookRepository NHibernateRepository 而不是 EFBookRepository。当然NHibernateRepository也要开发

  2. 使用接口允许您通过 MockObjects 实现出色的单元测试。您只需要实现 MockBookRepository 并在注入时使用它。有许多 Mock 框架可以帮助您 - 例如 Moq。

  3. 您可以在不更改代码的情况下动态切换存储库。例如,如果您的数据库暂时关闭,但您有另一个可以处理新订单的数据库,因为它们很重要(我知道这是个糟糕的例子)。在这种情况下,您检测到 DB 掉落并做出类似:

    currentRepository = temporaryOrdersOnlyRepository;

现在您的代码继续运行,除了您的获取数据和删除方法 returns 异常,但 CreateNewOrder() 方法会将订单保存到字符串文件)

祝你好运!

这是一项服务

public interface IFoodEstablishmentService
{
    Task<int> AddAsync(FoodEstablishment oFoodEstablishment);
    Task<int> UpdateAsync(FoodEstablishment oFoodEstablishment);
}

这是我的正常实现

public class FoodEstablishmentService : IFoodEstablishmentService
{
    public async Task<int> AddAsync(FoodEstablishment oFoodEstablishment)
    {
       // Insert Operation
        return result;
    }

    public async Task<int> UpdateAsync(FoodEstablishment oFoodEstablishment)
    {
        // Update Logic
        return result;
    }
}

这就是我的使用方式

IFoodEstablishmentService oFoodEstablishmentService =  new FoodEstablishmentService();
oFoodEstablishmentService.AddAsync(oFoodEstablishment);

但是等等,如果我可能需要通过队列而不是直接将插入逻辑传递给服务器,等待插入操作完成然后 return 结果,而不是传递队列然后队列工作人员处理那些操作? 因此,我没有弄乱一切,而是用相同的接口

实现了另一个 class
public class FoodEstablishmentQueueService : IFoodEstablishmentService
{
    public async Task<int> AddAsync(FoodEstablishment oFoodEstablishment)
    {
       // Insert Queue Operation
        return result;
    }

    public async Task<int> UpdateAsync(FoodEstablishment oFoodEstablishment)
    {
        // Update Queue Logic
        return result;
    }
}

这就是我使用它的方式,不破坏任何东西是不是很容易,而且如前面的回答所述,使用 DI Container 甚至效果更好

IFoodEstablishmentService oFoodEstablishmentService =  new FoodEstablishmentQueueService();
oFoodEstablishmentService.AddAsync(oFoodEstablishment);

我想不要选择最好的模式,而是从任何一个开始,然后慢慢地你会需要更多的东西,然后模式开始发挥作用存储库模式或通用存储库模式可能不是大规模的理想模式select 逻辑超出 select 模型数据的应用程序。请搜索 CQRS 模式。

那个教程很没用。它只是 EF 的 DbSet 的包装器。非常糟糕的例子。存储库模式本身意味着您需要根据 域需求 设计适当的接口。通常你至少有 3 个需求:添加、获取、保存。但一切都取决于您的领域,这一点很重要:没有秘诀,这正是应用程序所需要的。

存储库实现只是整个业务对象的 persisting/loading(其中业务对象是业务概念)。您选择了 Ado.net(您应该选择一个 micro-Orm,因为使用 ado.net 没有任何好处)与数据库通信。 OK,直接存到db,查询db例程。

没有 recipe/rule 如何实现存储库。 'hard'部分是设计界面。实现只是 class 使用数据库(以任何你想要的方式)。

我们使用接口是因为通常情况下,存储库的接口是域的一部分,而它的实现是持久性的一部分。这也允许多个存储库实现和轻松测试(通过模拟)。

顺便说一句,你要明白存储库模式只是一个简单的原则。想怎么实现就怎么实现,没有'correct'的方式。需要 'correct' 的接口 design 应该只使用业务对象,不应泄露任何实现细节(如 IQueryable)。