Мы пытаемся объединить объекты после исключения StaleObjectStateException, чтобы сохранить объединенную копию.
Вот наша экологическая ситуация:
- Пункт списка
- Многопользовательская система
- Настольное приложение WPF, база данных SQL Server 2008
- NHibernate 3.1.0.4000, FluentNHibernate 1.2.0.712
- Глобальные длительные сеансы NHibernate [на данный момент. Мы понимаем, что рекомендуется использовать сеанс на докладчика, но в настоящее время у нас нет времени на преобразование в расписании нашего проекта.]
- Сохранение сверху вниз и навигация по свойствам (то есть мы сохраняем объект верхнего уровня (в данном случае называемый Родителем) в нашем графе домена)
- .Cascade.AllDeleteOrphan () используется в большинстве случаев.
- Пользователи исключительно владеют некоторыми объектами в графе домена, но разделяют владение Родителем.
- Свойства навигации для дочерних объектов не существуют.
- Все классы имеют числовой идентификатор и числовые поля версии.
Пример использования:
- Пользователь 1 запускает приложение и открывает Родитель.
- Пользователь 2 запускает приложение и открывает Родитель.
- Пользователь 2 добавляет ребенка (здесь C2).
- Пользователь 2 сохраняет Родителя.
- Пользователь 1 добавляет ребенка (здесь C1).
- Пользователь 1 сохраняет Родителя.
- Пользователь 1 получает исключение StaleObjectStateException (и это правильно)
Мы хотим изящно обработать исключение. Поскольку пользователи разделяют владение родительским элементом, пользователь 1 должен иметь возможность успешно сохранять и сохранять родительский элемент как со своим новым дочерним элементом, так и с дочерним элементом пользователя 2.
Когда запускается SOSE, согласно Айенде (http://msdn.microsoft.com/en-us/magazine/ee819139.aspx):
ваш сеанс и его загруженные объекты являются тостовыми, потому что с NHibernate исключение, созданное из сеанса, переводит этот сеанс в неопределенное состояние. Вы больше не можете использовать этот сеанс или какие-либо загруженные объекты
C1 уже был назначен идентификатор и номер версии в сеансе, который сейчас не используется. (Я бы хотел, чтобы этого не было.)
Как совместить использование ISession.Merge () и ISession.Refresh (), чтобы получить только что сохраненный родительский элемент, имеющий как C1, так и C2?
Мы испробовали ряд загадочных перестановок, ни одна из которых не работает полностью. Обычно либо «строка была обновлена или удалена другой транзакцией (или отображение несохраненных значений было неверным», либо фактическая коллизия идентификаторов на уровне ODBC.
Наша теория на данный момент:
- Сбросить номера версий на C1 (чтобы предотвратить «неверное сопоставление несохраненных значений»)
- Получите новую сессию
- newSession.Refresh (C1);
- newParent = newSession.QueryOver [...]
- newParent.Add (C1);
- newSession.SaveOrUpdate (newParent)
Однако вся документация предполагает, что предполагается достаточно newSession.Merge.
Другие сообщения, использованные в качестве исследования:
Свободно владеет NHibernate. Новичок: строка была обновлена или удалена другой транзакцией
Есть ли альтернатива ISession.Merge (), которая не срабатывает при использовании оптимистической блокировки?
Строка StaleObjectstateException была обновлена или удалена
Как я могу указать NHibernate сохранять только измененные свойства