NHibernate не выдает исключение StaleObjectStateException при использовании <Version>и изменении данных в базе данных - PullRequest
1 голос
/ 01 декабря 2009

У меня есть сущность, сопоставленная в NHibernate с оптимистичным управлением параллелизмом, использующая столбец отметки времени SQL в качестве номера версии. Отображение выглядит следующим образом:

<class name="Entity" optimistic-lock="version" discriminator-value="0">
    <id name="id">
        <generator class="native" />
    </id>
    <version name="Version" column="Version" generated="always" unsaved-value="null" type="System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    ...
    <subclass name="ChildEntity" discriminator-value="1" />
</class>

Я проверяю, что происходит, когда данные в строке в базе данных изменяются между получением и обновлением записи. Для этого я запускаю оператор обновления непосредственно для одной из записей в таблице, которые находятся в процессе обновления NHibernate. Это прямое обновление изменяет номер версии записи в таблице.

Как и ожидалось, управляемое обновление NHibernate не происходит в определенной строке (это хорошо). Тем не менее, исключение не выдается во время фиксации. Я ожидал, что StaleObjectStateException произойдет, когда транзакция будет зафиксирована, чтобы я мог откатить транзакцию и сообщить пользователю. Разве это не ожидаемое поведение? Я что-то упустил?

Мой код для фиксации транзакции выглядит примерно так:

_session.BeginTransaction();
...
// load objects in session
IList<ChildEntity> toChange = _session.Find('some condition');
foreach ( var itemToChange in toChange )
{
     itemToChange.Status = Status.Updated;
}
...
_session.Transaction.Commit();

Элементы принадлежат одному и тому же сеансу, и все работы выполняются за одну транзакцию. ChildEntity является подклассом базового класса Entity, для которого оптимистическая блокировка установлена ​​в версию.

Ответы [ 2 ]

5 голосов
/ 01 декабря 2009

Как вы меняете данные? StaleObjectException генерируется только тогда, когда NHibernate пытается обновить строку и номер версии больше не совпадает. Другие столбцы не имеют значения. Возможно ли, что при тестировании вы не обновляете номер версии?

Предпосылка заключается в следующем:

A. Пользователь A & B получает объект из базы данных с версией = 1

SQL: SELECT [object] FROM [TABLE] where id = [id] and Version = 1

B. Пользователь A Обновляет объект, который изменяет версию на 2

SQL: UPDATE [TABLE] SET [object] (& Set Version = 2) where id = [id] and Version = 1 возвращает 1 обновленную строку

C. Пользователь B пытается обновить объект, но получает StaleObjectException как объект обновления с версией = 1 (версия, которую он получил, шаг 1) обновляет 0 записей в базе данных.

SQL: UPDATE [TABLE] SET [object] where id = [id] and Version = 1 возвращает 0 обновленных строк и генерирует исключение StaleObjectException.

0 голосов
/ 01 декабря 2009

Похоже, что мои тесты были неточными. В тесте я делал get ПОСЛЕ того, как другая транзакция обновила запись. Это другое обновление сделало строку непригодной для обновления, поэтому обновление не было предпринято. Когда я изменил тест, чтобы сделать конкурирующее обновление ПОСЛЕ получения, то возникла исключительная ситуация StaleObjectStateException.

Извините за путаницу.

...