Проблема с NHibernate и сохранением - NHibernate не обнаруживает изменения и использует старые значения - PullRequest
0 голосов
/ 14 марта 2010

Когда я делаю это:

Cat x = Session.Load<Cat>(123);
x.Name = "fritz";
Session.Flush();

NHibernate обнаруживает изменение и ОБНОВЛЯЕТ БД. Но когда я делаю это:

Cat x = new Cat();
Session.Save(x);
x.Name = "fritz";
Session.Flush();

Я получаю NULL для имени, потому что это было то, что было, когда я звонил Session.Save(). Почему NHibernate не обнаруживает изменения или, что еще лучше, принимает значения для оператора INSERT во время Flush()?

Добавлено: Для пояснения: Session.FlushMode установлено на None, поэтому автоматических сбросов пока я не скажу. Я также использую первичные ключи GUID (с генератором guid.comb).

Причина, по которой я это делаю, заключается в том, что я использую Сессию как трекер "грязности". Я пишу приложение для Windows Forms, и каждая из моих форм имеет отдельный сеанс, который длится столько же, сколько и форма. Сессия по возможности максимально отключена, чтобы у меня не заканчивались соединения ADO.NET (это приложение MDI, и нет ограничений на количество форм, которые можно открыть). Каждая форма также имеет кнопку «ОК» и кнопку «Отмена». Кнопка «ОК» вызывает Session.Flush(), а затем закрывает форму; кнопка «Отмена» просто закрывает форму и молча отменяет все изменения, сделанные пользователем.

Ну, по крайней мере, это то, что я хотел бы. Вышеуказанная ошибка вызывает у меня проблемы.

Ответы [ 2 ]

0 голосов
/ 14 марта 2010

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

Мы сталкиваемся с похожими проблемами с нашим приложением Windows Forms, и я думаю, что мы собираемся использовать другой подход.FlushMode остается в Auto (по умолчанию), и объект удаляется (ISession.Evict) из сеанса, если пользователь отменяет операцию.Выселение объекта делает его преходящим, что в точности соответствует желаемому поведению.

0 голосов
/ 14 марта 2010

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

using (var session = createSession())
{
   using (var transaction = session.BeginTransaction())
   {
      Cat x = new Cat();
      session.Save(x);
      x.Name = "fritz";
      try
      {
          transaction.Commit();
      }
      catch
      {
          // prevents your database from getting corrupt when you have a bug
          transaction.RollBack();
          throw;
      }
   }
}

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

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