草叶睡蜢

导航

4.3 Repositories 存储层

Repositories 存储层

A Repository is a collection-like interface that is used by the Domain and Application Layers to access to the data persistence system (the database) to read and write the Business Objects, generally the Aggregates.
存储库是一个类似于集合的接口,被领域层和应用层用来访问数据持久化系统(数据库)以读写业务对象,通常是聚合体。

Common Repository principles are;
常见的存储库原则,如下:

  • Define a repository interface in the Domain Layer (because it is used in the Domain and Application Layers), implement in the Infrastructure Layer (EntityFrameworkCore project in the startup template).
  • 在领域层定义一个存储库接口(因为它在领域层和应用层中使用),在基础设施层(启动模板中的EntityFrameworkCore项目)实现。
  • Do not include business logic inside the repositories.
  • 不要在存储库里写入业务逻辑代码。
  • Repository interface should be database provider / ORM independent. For example, do not return a DbSet from a repository method. DbSet is an object provided by the EF Core.
  • 存储库接口应该是独立于数据库提供者/ORM的。例如,不要从存储库方法中返回一个DbSet。DbSet是一个由EF Core提供的对象。
  • Create repositories for aggregate roots, not for all entities. Because, sub-collection entities (of an aggregate) should be accessed over the aggregate root.
  • 为聚合根创建存储库,而不是为所有实体创建存储库。因为,(一个聚合体的)子集实体应该在聚合根上被访问。
Do Not Include Domain Logic in Repositories 不要在存储库中包括领域逻辑

While this rule seems obvious at the beginning, it is easy to leak business logic into repositories.
虽然这条规则在开始时似乎很明显,但很容易将业务逻辑泄漏到存储库中。

Example: Get inactive issues from a repository 示例:从存储库中获取不活动的问题

image

IIssueRepository extends the standard IRepository<...> interface by adding a GetInActiveIssuesAsync method. This repository works with such an Issue class:
IIssueRepository扩展了标准的IRepository<...>接口,增加了一个GetInActiveIssuesAsync方法。这个存储库与这样的Issue类一起工作。

image

(the code shows only the properties we need for this example)
(代码中只显示了我们在这个例子中需要的属性)

The rule says the repository shouldn't know the business rules. The question here is "What is an inactive issue? Is it a business rule definition?"
这条规则说存储库不应该知道业务规则。这里的问题是 "什么是不活动的问题?它是一个业务规则的定义吗?"

Let's see the implementation to understand it:
让我们看看实现代码来理解它:

image

(Used EF Core for the implementation. See the EF Core integration document to learn how to create custom repositories with the EF Core.)
(使用EF Core来实现。参见EF Core集成文档,了解如何使用EF Core创建自定义存储库)。

When we check the GetInActiveIssuesAsync implementation, we see a business rule that defines an in-active issue: The issue should be open, assigned to nobody, created 30+ days ago and has no comment in the last 30 days.
当我们查看GetInActiveIssuesAsync的代码实现时,我们看到一个定义非活动问题的业务规则是:该问题应该是开放的,没有分配给任何人,在30天之前创建的,并且在近30天内没有评论。

This is an implicit definition of a business rule that is hidden inside a repository method. The problem occurs when we need to reuse this business logic.
这是一个隐藏在存储库方法中的业务规则的隐性定义。当我们需要重复使用这个业务逻辑时,问题就出现了。

For example, let's say that we want to add an bool IsInActive() method on the Issue entity. In this way, we can check activeness when we have an issue entity.
例如,假设我们想在Issue实体上添加一个bool IsInActive()方法。通过这种方式,我们可以在获得Issue实体的时候检查其活跃性。

Let's see the implementation:
让我们看看代码实现情况:

image

We had to copy/paste/modify the code. What if the definition of the activeness changes? We should not forget to update both places. This is a duplication of a business logic, which is pretty dangerous.
我们不得不复制/粘贴/修改代码。如果活动性的定义改变了怎么办?我们不应该忘记更新这两个地方。这是一个业务逻辑的重复,是相当危险的。

A good solution to this problem is the Specification Pattern!
解决这个问题的一个很好的办法就是规范化模式!

posted on 2021-12-08 16:02  草叶睡蜢  阅读(122)  评论(0编辑  收藏  举报