Я не уверен, как наилучшим образом реализовать представление основных деталей в сочетании с ORM.Приложение использует WPF с MVVM и отображает сетку всех доступных объектов, а также подробную информацию о выбранном в данный момент объекте.
ViewModel представления довольно прост, оно имеет:
- An
ObservableCollection<ItemViewModel> Items
, где ItemViewModel
- это ViewModel для объекта домена, который должен отображаться в представлении.Это свойство привязано к сетке. - A
ItemViewModel CurrentItem
свойство, которое привязано к сетке SelectedItem
. ICommand
для «Добавить новый элемент», «Удалить выбранный элемент»и «Сохранить изменения в выбранном элементе».
Мое приложение использует NHibernate в качестве инструмента ORM, но я не хочу утекать NHibernate по всей базе кода, поэтому я абстрагировал его с помощью «Единицы работы»Шаблоны "и" Репозиторий ".
Специфическая реализация этих шаблонов в NHibernate такова, что" Единица работы "открывает новый сеанс NHibernate и транзакцию в начале и в конце фиксирует транзакцию и удаляет сеанс,Таким образом, время жизни единицы работы, сеанса и транзакции одинаково.Единица работы имеет свойство Repository
, которое использует тот же сеанс, что и единица работы, а также имеет то же время жизни.
Вот где оно становится проблематичным: я хотел бы заполнить Items
Коллекция в конструкторе MasterDetailViewModel
.В настоящее время мне нужно создать новую единицу работы и заполнить коллекцию.Чтобы не иметь долго выполняющихся транзакций, UoW должен быть удален непосредственно после этого, удаляя также базовый сеанс.
Теперь, когда пользователь хочет сохранить изменения в текущем элементе, мне нужно будет открыть другой UoW, извлечьобъект из базы данных, обновите его текущими значениями ItemViewModel
, сохраните его в базе данных и утилизируйте UoW.
Однако этот подход имеет несколько важных недостатков:
- Мой код замусорен
using(var uow = uowFactory.StartNew())
. - Оптимистическая блокировка не выполняется.Если кто-то другой изменил бы тот же элемент в базе данных, его изменение было бы перезаписано.
- Для обновления элемента требуется два попадания в базу данных вместо одного.
Это приводитЯ пришел к выводу, что реализация моего UoW имеет недостатки.
Я думал об изменении реализации так, чтобы отношения между UoW и репозиторием были обратными.Это будет означать, что IoC внедрит репозиторий в ViewModel вместо UnitOfWorkFactory.Репозиторий теперь является функциональным эквивалентом ISession
от NHibernate.Репозиторий может запустить новый UoW, который теперь идентичен транзакции базы данных.
Это хорошо подходит для моего сценария Master / Detail, но он не поддерживает понятие «бизнес-транзакции», которое обычно используется в качестве синонима.для единицы работы, например, логическая транзакция, охватывающая несколько транзакций базы данных и запрос пользователя.
Вопрос заключается в следующем: как наилучшим образом реализовать две модели: единицу работы и репозиторий, чтобы их можно было использовать в обоих сценариях?