存储库的预期行为

发布于 2024-11-08 14:11:49 字数 1112 浏览 8 评论 0原文

我正在编写一个 ORM,并且不确定存储库的预期行为,或者更准确地说,存储库和工作单元之间的边界。 根据我的理解,存储库可能如下所示:

interface IPersonRepository
{
    public function find(Criteria criteria);
    public function add(Person person);
    public function delete(Person person);
}

根据 Fowler(PoEAA,第 322 页):

存储库在域和数据映射层之间进行中介,其作用类似于内存中的域对象集合。 [...] 可以在存储库中添加和删除对象,就像在简单的对象集合中一样。

这意味着以下测试应该有效(假设我们已经保存了一个 Person,其姓氏是 Fowler):

collection = repository.find(lastnameEqualsFowlerCriteria);
person = collection[0];

assertEquals(person.lastname, "Fowler");

person.lastname = "Evans";
newCollection = repository.find(lastnameEqualsFowlerCriteria);

assertFalse(newCollection.contains(person));

这意味着当映射到数据库时,即使某处没有调用显式 save() 方法,该 Person模型必须已由存储库自动保​​留,以便下一个查询返回正确的集合,包含原始 Person。

但是,这不正是工作单元的作用吗?决定将哪个模型以及何时保存到数据库?

在上面的实现中,Repository 在收到另一个 find() 调用时必须决定保留先前检索到的 Person,以便结果与修改一致。但如果没有发出其他 find() 调用,则该模型根本不会隐式持久化。

在工作单元的上下文中,这并不是真正的问题,因为我们可以在开始时启动一个事务,并在需要时回滚任何对数据库的插入。 但是单独使用时,这个存储库不会导致意外的、不可预测的行为吗?

I'm writing an ORM and am unsure of the expected behaviour of the Repository, or more precisely, the frontier between the Repository and the Unit Of Work.
From my understanding, a Repository might look like this:

interface IPersonRepository
{
    public function find(Criteria criteria);
    public function add(Person person);
    public function delete(Person person);
}

According to Fowler (PoEAA, page 322):

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. [...] Objects can be added to and removed from the Repository, as they can from a simple collection of objects.

This would imply that the following test should work (assuming that we already have a Person persisted, whose last name is Fowler):

collection = repository.find(lastnameEqualsFowlerCriteria);
person = collection[0];

assertEquals(person.lastname, "Fowler");

person.lastname = "Evans";
newCollection = repository.find(lastnameEqualsFowlerCriteria);

assertFalse(newCollection.contains(person));

That means that when mapping to a database, even if no explicit save() method has been called somewhere, the Person model must have been automatically persisted by the Repository, so that the next query returned the correct collection, not containing the original Person.

But, isn't that the role of the Unit Of Work, to decide which model to persist to the database, and when?

In the above implementation, the Repository has to decide to persist the Person previously retrieved when receiving another find() call, so that the result is consistent with the modification. But if no other find() call were issued, the model would not have been persisted implicitly at all.

In the context of a Unit Of Work, it is not really a problem, because we can start a transaction at the beginning, and rollback any insert to the db anyway if needed.
But when used alone, can't this Repository lead to unexpected, unpredictable behaviour?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

め七分饶幸 2024-11-15 14:11:49

存储库在
域和数据映射层,作用
就像内存中的域对象
收藏。 [...]可以添加对象
到存储库并从存储库中删除,如
他们可以从一个简单的集合
对象。

这并不意味着您不需要保存方法。您仍然需要显式地将更改提交到存储。

请参阅工作单元模式和持久性无知

public interface IUnitOfWork {
  void MarkDirty(object entity);
  void MarkNew(object entity);
  void MarkDeleted(object entity);
  void Commit();
  void Rollback();
}

在某种程度上,您可以将工作单元视为转储所有事务处理代码的地方。工作单元的职责是:

  • 管理事务。
  • 排序数据库插入、删除和更新。
  • 防止重复更新。在工作单元对象的单次使用中,代码的不同部分可能会将同一个发票对象标记为已更改,但工作单元类只会向数据库发出单个 UPDATE 命令

A Repository mediates between the
domain and data mapping layers, acting
like an in-memory domain object
collection. [...] Objects can be added
to and removed from the Repository, as
they can from a simple collection of
objects.

This does not mean you do not need a save method. You still need to explicitly commit your changes to storage.

See The Unit Of Work Pattern And Persistence Ignorance

public interface IUnitOfWork {
  void MarkDirty(object entity);
  void MarkNew(object entity);
  void MarkDeleted(object entity);
  void Commit();
  void Rollback();
}

In a way, you can think of the Unit of Work as a place to dump all transaction-handling code. The responsibilities of the Unit of Work are to:

  • Manage transactions.
  • Order the database inserts, deletes, and updates.
  • Prevent duplicate updates. Inside a single usage of a Unit of Work object, different parts of the code may mark the same Invoice object as changed, but the Unit of Work class will only issue a single UPDATE command to the databas
苍景流年 2024-11-15 14:11:49

我认为您要问的是以下内容: http://martinfowler.com/eaaCatalog/identityMap.html< /a>

存储库应将获取的对象保留在内存中,并且不应从持久性存储中检索对该实体的所有后续调用,因此您的示例应该可以正常工作。

I think what you;re asking about is following: http://martinfowler.com/eaaCatalog/identityMap.html

Repository should keep fetched objects in memory and all subsequent calls for that entity should not be retrieved from persistence storage, hence your example should work fine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文