NHibernate session.flush () не работает, но вносит изменения - PullRequest
0 голосов
/ 05 декабря 2009

У нас есть таблица базы данных SQL Server, которая состоит из идентификатора пользователя, некоторого числового значения, например, баланс и столбец версии.

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

  1. загрузить текущую строку (сопоставленную с типом).
  2. внести изменения в значение, основанное на старом значении. (например, добавить 50).
  3. Session.update (OBJ)
  4. session.flush () (поскольку мы настроены оптимистично, мы хотим убедиться, что у нас было правильное значение версии до обновления)
  5. если на шаге 4 (сбросить) возникло исключение StaleStateException, обновить объект (с помощью lockmode.read) и перейти к шагу 1

мы делаем это только определенное количество раз за логическую транзакцию, если мы не можем зафиксировать ее после X попыток, мы отклоняем логическую транзакцию.

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

в чем здесь проблема, спросите вы? хорошо, при коммитах мы видим изменения в неудачных логических объектах в частности, если значение было 50, когда мы прошли шаг 1 (впервые), и мы попытались обновить его до 100 (но мы потерпели неудачу, поскольку, например, другой поток изменил его на 70), тогда значение 50 фиксируется для этот ряд очевидно, это неверно.

Чего нам здесь не хватает?

Ответы [ 4 ]

2 голосов
/ 05 декабря 2009

Ну, у меня нет тонны опыта здесь, но я помню одну вещь, прочитав в документации , это то, что если возникает исключение, вы должны немедленно откатить транзакцию и удалить сеанс,Возможно, ваша проблема связана с тем, что сеанс находится в несогласованном состоянии?

Кроме того, вызов обновления в вашем коде здесь не требуется .Поскольку вы загрузили объект в этом сеансе, он уже отслеживается с помощью nhibernate.

1 голос
/ 05 декабря 2009

Если вы все-таки хотите внести изменения, зачем вам управление версиями строк? Похоже, вы должны получить тот же результат, если вы просто всегда обновляете данные и позволяете выиграть последней транзакции.

Относительно того, почему обновление становится постоянным, это зависит от того, как выглядят операторы SQL для проверки / обновления версии, и от управления транзакциями, которое вы исключили из примера кода. Если вы включите ведение журнала Hibernate SQL, вероятно, станет понятно, как это происходит.

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

Вот документация для исключения в сеансе http://nhibernate.info/doc/nhibernate-reference/best-practices.html

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

Я не гуру из nhibernate, но ответ кажется простым.

Когда nhibernate загружает объект, он ожидает, что он не изменится в БД, пока он находится в кеше сеанса nhibernate.

Как вы упомянули - у вас есть многопоточное приложение.

Вот что происходит =>

  • 1-й поток загружает сущность
  • 2-й поток загружает сущность
  • 1-й поток меняет сущность
  • 2-й поток изменяет сущность и => обнаруживает, что загруженная сущность изменилась чем-то другим, и, опасаясь, что она испортила изменения, сделанные в 1-м потоке - выдает исключение, чтобы позволить программисту знать об этом.

Вам не хватает механизма блокировки. Не могу много рассказать о том, как правильно и элегантно применить это. Может быть, Transaction поможет.

У нас были похожие проблемы, когда мы использовали nhibernate и raw ado.net одновременно (к счастью - только для запросов - по крайней мере, для производственного кода). Все, что нам нужно было сделать - принудительно обновить базу данных при вставке / обновлении, чтобы мы могли на самом деле запросить что-то через полнотекстовый поиск некоторых конкретных объектов.

Было StaleStateException в интеграционных тестах, когда мы использовали raw ado.net для сброса БД. Сессия NHibernate была жива через кучу тестов, но каждый тест пытался очистить БД без ведома NHibernate.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...