当查询相同的 ID 时,存储库是否应该始终 return 内存中的相同引用?

Should a repository always return the same reference in memory when querying for the same ID?

在许多博客或文章中,您会读到以下关于存储库的声明

You should think of a repository as a collection of domain objects in memory

现在我在问自己,当我为同一个 ID 查询存储库两次时会发生什么。

Entity a = theRepo.GetById(1);
Entity b = theRepo.GetById(1);

assertTrue( a == b ); // Do they share the same reference ?
assertTrue( a.equals( b ) ); // This should always be true

我认为您不能假设 a == b

考虑您获得实例 a 并开始修改它的情况,但尚未将其保存回您的数据库。如果另一个线程请求同一个实体并将其放入变量 b,它应该得到一个反映数据库中数据的新实体,而不是另一个线程正在修改但尚未修改(并且可能永远不会)的脏实体) 保存。

另一方面,假设 ab 在从同一个存储库中检索到之后没有被后续修改,那么可以安全地假设 a.equals(b) ,同时假设 equals() 方法已为实体正确实施。

在我看来,您的问题归结为存储库的生命周期。存储库是瞬态的(理想情况下),而且有时它们位于另一个名为 "Unit of Work" 的 class 中,这也是瞬态的。

我认为这不是 DDD 问题,而是基础架构问题。

给定实体类型,存储库是给定实体类型实例的集合。

存储库不创建实体的实例。它只是您之前创建的实例的集合(在 "set" 的意义上)。然后将这些实例添加到存储库(实例集)。您可以检索这些实例。

集合不重复元素。给定一个 id(例如 id=1),该集合将只有一个 id=1 的实例,并且该实例是您调用 "theRepo.GetById(1)".

时检索到的实例

所以:

Entity a = theRepo.GetById(1);

Entity b = theRepo.GetById(1);

Should the repository always return the same reference in memory ?

参见更新 3。

Should the repository return a new instance of the entity but with equal state?

没有。存储库应该 return 您之前添加的实例。存储库不应创建新实例。

无论如何,为了检查两个实例是否相同,你不应该比较引用,你应该比较它们的 id。

你在混淆概念。存储库只是实例的集合(集)。实例由工厂(或实体的构造方法)创建。

请参阅 Vaughn Vernon 的 IDDD 书(第 12 章的 "Collection-Oriented Repositories" 部分)。

希望对您有所帮助。

更新:

当我说“...存储库是一组实例...”时,我的意思是它模仿了一组。我的错没有表达好。关于更新存储库的实例,这样的操作不存在,因为当您检索实例并修改它时,更改是在存储库的实例中进行的,您不必重新保存实例。实现存储库的持久性机制必须具有确保这种行为的能力。请参阅 Vaugn Vernon 的《实施 DDD》一书的第 12 章。

更新 2:

我想澄清一下,我在这里所说的是我在阅读 Vaughn Vernon 的书 IDDD 以及另一本书(PHP 中的领域驱动设计,Carlos Buenosvinos 着)后的理解。我根本不想误导。

更新 3:

我问了 Vaughn Vernon 以下问题:

关于面向集合的存储库,我有一个问题: 如果我这样做 Foo aFoo=fooRepository.getById(1); Foo anotherFoo=fooRepository.getById(1); 那么是否保证两个引用相同(aFoo==anotherFoo)?

他回答了以下问题:

这取决于支持的持久化机制,例如Hibernate/JPA。如果您在两次读取中使用相同的会话并且两次读取具有相同的事务范围,那么似乎应该这样做,但请检查您的 ORM。