NHibernate не выдает исключение StaleObjectStateException при использовании ‹Version› и изменении данных в базе данных

У меня есть объект, сопоставленный в 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, для которого оптимистическая блокировка установлена ​​на версию.


person SteveBering    schedule 01.12.2009    source источник


Ответы (2)


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

Предпосылка такова:

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

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

B. Объект User A Updates, который изменяет версию на 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.

person Michael Gattuso    schedule 01.12.2009

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

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

person SteveBering    schedule 01.12.2009