Вложенный пользовательский интерфейс, требующий вложенных транзакций в ActiveRecord - PullRequest
0 голосов
/ 03 августа 2011

У меня есть диалог D1, который редактирует тип модели M1, и другой диалог D2, который редактирует тип модели M2.Одна из вещей, которые содержит M2, - это ссылка на M1, и поэтому для удобства пользователя D2 содержит кнопку, которая запускает D1, в дополнение к тому, что D1 и D2 доступны с верхнего уровня.

Каждый из D1 и D2 создает TransactionScope (используя TransactionMode.New) при входе, изменяет объекты модели (M1 или M2), когда пользователь взаимодействует с диалоговым окном, и выполняет фиксацию / откат в зависимости от ситуации, когда пользователь нажимает кнопку OK / Отмена.кнопки.

Это прекрасно работает в отдельности, когда диалоги открываются с верхнего уровня.

Когда D1 открывается изнутри D2, ожидаемое поведение заключается в том, что нажатие OK в D1 должно немедленно сохранитьв базу данных, и изменения в M1 должны стать видимыми для D2.(D2 может затем сохранить или отменить свои собственные изменения в M2, не влияя на M1.)

На самом деле происходит то, что изменения в M1, похоже, сохраняются в базе данных, когда D1 закрывается (и до того, как D2 закрывается), но D2 не может видеть изменения в M1 - предположительно, потому что сеанс / транзакция в D2 думает, что он имеет современные объекты, поэтому не запрашивает базу данных, даже когда вызывается FindFirst и т. д.Есть ли какой-нибудь способ заставить его (не теряя изменений в M2)?

(Другое странное поведение состоит в том, что оба D1 и D2 подключаются к TransactionScope.OnCompleted, но это срабатывает только на D1, когда D2 закрыт дляслучай, когда D1 вызывается из D2.)

1 Ответ

0 голосов
/ 03 августа 2011

Хорошо, я думаю, что нашел что-то, что работает, но это немного уродливо, поэтому я все еще интересуюсь лучшими ответами.

Хитрость заключалась в том, чтобы модифицировать D1 так, чтобы при его вызовевложив, после совершения своей собственной транзакции (и, таким образом, возврата в область транзакции D2), повторно Find объекты, которые он только что изменил, и Refresh их.

И он может обнаружить, что находится в этом вложенном сценариипотому что OnCompleted не вызывали, когда Dispose d выполняла свою собственную транзакцию.

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

...