Я видел шаблон единицы работы, реализованный с помощью чего-то вроде следующего кода:
private HashSet<object> _newEntities = new HashSet<object>();
private HashSet<object> _updatedEntities = new HashSet<object>();
private HashSet<object> _deletedEntities = new HashSet<object>();
а затем существуют методы для добавления сущностей в каждый из этих HashSets.
При фиксации UnitOfWork создает несколько экземпляров Mapper для каждой сущности и вызывает методы Insert, Update, Delete из некоторого воображаемого Mapper.
Проблема с этим подходом для меня заключается в том, что имена методов Insert, Update, Delete жестко запрограммированы, поэтому кажется, что такой UnitOfWork способен выполнять только простые операции CRUD. Но что, если мне понадобится следующее использование:
UnitOfWork ouw = new UnitOfWork();
uow.Start();
ARepository arep = new ARepository();
BRepository brep = new BRepository();
arep.DoSomeNonSimpleUpdateHere();
brep.DoSomeNonSimpleDeleteHere();
uow.Commit();
Теперь подход с тремя HashSet терпит неудачу, потому что тогда я мог зарегистрировать сущности A и B только для операций вставки, обновления, удаления, но сейчас мне нужны эти пользовательские операции.
Так что, похоже, я не могу всегда складывать операции репозитория и затем выполнять их все с UnitOfWork.Commit();
Как решить эту проблему? Первая идея - я мог бы хранить адреса методов
arep.DoSomeNonSimpleUpdateHere();
brep.DoSomeNonSimpleDeleteHere();
в экземпляре UoW и выполнить их на uow.Commit()
, но затем я должен также сохранить все параметры метода. Это звучит сложно.
Другая идея состоит в том, чтобы сделать репозитории полностью UoW-осведомленными: в DoSomeNonSimpleUpdateHere
я могу обнаружить, что UoW работает, и поэтому я не выполняю DoSomeNonSimpleUpdateHere
, но сохраняю параметры операции и статус 'ожидание' в некотором стеке экземпляра репозитория (очевидно, я не могу сохранить все в UoW, потому что UoW не должен зависеть от конкретных реализаций репозитория). А затем я регистрирую соответствующий репозиторий в экземпляре UoW. Когда UoW вызывает Commit
, он открывает транзакцию и вызывает что-то вроде Flush () для каждого ожидающего хранилища. Теперь каждый метод репозитория нуждается в некотором материале для обнаружения UoW и отсрочки работы на более поздний срок Commit()
.
Итак, короткий вопрос - как проще всего зарегистрировать все ожидающие изменения в нескольких репозиториях в UoW, а затем Commit()
все они в одной транзакции?