Отношения между хранилищем и единицей работы

17

Я собираюсь реализовать репозиторий, и я хотел бы использовать шаблон UOW, так как пользователь репозитория может выполнять несколько операций, и я хочу зафиксировать их сразу.

Прочитав несколько статей по этому вопросу, я все еще не понимаю, как соотнести эти два элемента, в зависимости от статьи, которая делается другим способом.

Иногда UOW является чем-то внутренним для хранилища:

public class Repository
{
    UnitOfWork _uow;

    public Repository()
    {
       _uow = IoC.Get<UnitOfWork>();
    }

    public void Save(Entity e)
    {
        _uow.Track(e);
    }

    public void SubmittChanges()
    {
        SaveInStorage(_uow.GetChanges());
    }
}

И иногда это внешнее:

public class Repository
{
    public void Save(Entity e, UnitOfWork uow)
    {
        uow.Track(e);
    }

    public void SubmittChanges(UnitOfWork uow)
    {
        SaveInStorage(uow.GetChanges());
    }
}

В других случаях, UOW ссылается на хранилище

public class UnitOfWork
{
    Repository _repository;

    public UnitOfWork(Repository repository)
    {
       _repository = repository;
    }

    public void Save(Entity e)
    {
        this.Track(e);
    }

    public void SubmittChanges()
    {
       _repository.Save(this.GetChanges());
    }
}

Как связаны эти два элемента? UOW отслеживает элементы, которые необходимо изменить, и хранилище содержит логику для сохранения этих изменений, но ... кто кого называет? Последнее имеет больше смысла?

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

ура

NullOrEmpty
источник

Ответы:

7

Re: «UOW отслеживает элементы, которые должны быть изменены, и хранилище содержит логику для сохранения этих изменений, но ... кто кого называет?»

Вы понимаете основные обязанности этих классов. Вы говорите, что каждая из статей, которые вы прочитали, соединяет их по-разному. Это подразумевает, что решение о том, «кто кому звонит», остается за вами.

Я бы попытался обрисовать проблему в терминах «слоев» в то время, руководствуясь основными принципами хорошего дизайна программного обеспечения , таких как Сплоченность , Расцепление , переиспользуемость , Unit-тестируемость и т.д.

Процитируем Эрик Эванс «Домен-управляемый дизайн» (2004) Addison Wesley, стр. 69 :

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

По моему мнению, UOW и Repo - это два совершенно разных класса, которые несут четкую, независимую ответственность. Начнем с того, что я не заставлю ни одного из них ссылаться на другого.

Я думаю, что вам нужен какой-то третий клиентский класс (т.е. либо a, controllerлибо service class), который действительно знает «когда и что получить» из репо и «когда», чтобы сохранить транзакцию. Этот клиент находится относительно высоко в архитектуре (поэтому может знать о большем количестве классов) и может выполнять некоторую оркестровку между ними.

--------------------------------

         [Client]
           /   \
----------/---- \---------------
         /       \
        V         V
[Unit Of Work]  [Repo]


--------------------------------
JW01
источник
2

Методы чаще всего передаются интерфейсу UOW (который обычно создается через фабрику).

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

У Microsoft очень подробный пост о шаблоне UOW:

http://msdn.microsoft.com/en-us/magazine/dd882510.aspx

Грэм Викстед
источник