Ожидаемое поведение репозитория

Я пишу ORM и не уверен в ожидаемом поведении Репозитория или, точнее, границы между Репозиторием и Единицей Работы. Насколько я понимаю, хранилище может выглядеть так:

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

По словам Фаулера (PoEAA, стр. 322):

Репозиторий является посредником между доменом и слоями отображения данных, действуя как коллекция объектов домена в памяти. [...] Объекты могут быть добавлены и удалены из репозитория, как и из простой коллекции объектов.

Это будет означать, что следующий тест должен работать (при условии, что у нас уже есть Персона, чья фамилия Фаулер):

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.

Но не в этом ли роль единицы работы, решить, какую модель сохранить в базе данных и когда?

В вышеприведенной реализации репозиторий должен принять решение о сохранении ранее извлеченного лица при получении другого вызова find(), чтобы результат соответствовал модификации. Но если бы не был выполнен другой вызов find(), модель не сохранялась бы вообще неявно.

В контексте единицы работы это на самом деле не проблема, потому что мы можем начать транзакцию в начале и откатить любую вставку в базу данных в любом случае, если это необходимо. Но может ли этот репозиторий, если он используется один, привести к неожиданному, непредсказуемому поведению?

2 ответа

Решение

Репозиторий является посредником между доменом и слоями отображения данных, действуя как коллекция объектов домена в памяти. [...] Объекты могут быть добавлены и удалены из репозитория, как и из простой коллекции объектов.

Это не значит, что вам не нужен метод сохранения. Вам все еще нужно явно зафиксировать ваши изменения в хранилище.

См . Единицу работы, образец и невежество

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

В некотором смысле, вы можете рассматривать Единицу Работы как место для выгрузки всего кода обработки транзакций. В обязанности подразделения входит:

  • Управлять транзакциями.
  • Заказать базу данных вставки, удаления и обновления.
  • Предотвратить повторяющиеся обновления. Внутри одного использования объекта Unit of Work разные части кода могут пометить один и тот же объект Invoice как измененный, но класс Unit of Work будет выдавать только одну команду UPDATE для баз данных

Я думаю, что вы спрашиваете о следующем: http://martinfowler.com/eaaCatalog/identityMap.html

Репозиторий должен хранить извлеченные объекты в памяти, и все последующие вызовы для этого объекта не должны извлекаться из постоянного хранилища, поэтому ваш пример должен работать нормально.

Другие вопросы по тегам