Обновление NHibernate не работает - PullRequest
8 голосов
/ 26 января 2009

Я не могу заставить работать мое обновление. Тест не пройден, и я не вижу сообщений об обновлении, отправляемых в базу данных. Может кто-нибудь сказать мне, что я делаю не так?

Это процедура обновления моего репозитория:

public void UpdateProject(Project proj)
{
    Session.Update(proj);
}

Это тестовый модуль, который я пытаюсь:

[Test]
public void Can_Update_A_Project()
{
    var project = _projects[0];
    project.Name = "test project";

    repository.UpdateProject(project);

    var fromDb = repository.GetAProject(_projects[0].ID);
    Assert.AreEqual(project.Name, fromDb.Name);        
}

Тест всегда терпит неудачу. Я вижу, как вставляются тестовые данные, и я вижу выбор для теста. Чего мне не хватает?

Спасибо!

Ответы [ 6 ]

20 голосов
/ 26 января 2009

Есть несколько вещей, которые могут происходить.

1) Сбой обновления, и NHibernate вызывает исключение, которое где-то проглатывается - это может произойти в зависимости от того, как вы настроили вещи. Поэтому в VS убедитесь, что все исключения вызовут перерыв.

2) Обновление кэшируется и не записывается напрямую в БД - вы можете принудительно записать данные, используя Repository.Flush();

3) Вы уверены, что _projects [0] прочитан из БД - я предполагаю, что это происходит в TestSetup? В противном случае NHibernate не будет осознавать это как объект, который находится под его «контролем».

Кстати: хорошая практика - читать данные, которые вы собираетесь изменить, в самом тесте, а затем отменить это изменение, вернув БД в исходное состояние. Таким образом, ваша тестовая БД не будет изменена вашим тестированием.

BTW2 - В приведенном выше тесте, если project.Name уже обновлялось один раз, т.е. тест успешно выполнен. Затем в следующий раз тест завершится успешно, даже если само обновление завершится неудачно. Способ избежать этого - добавить DateTime к проекту. Имя, не устанавливайте для него фиксированное значение.

6 голосов
/ 26 января 2009

Другое дело так: когда вы сохраняете объект, используя сеанс, и загружаете тот же объект из того же сеанса, используя идентификатор объекта, вы получите тот же экземпляр, который вы сохранили, независимо от того, были ли какие-либо вставки или обновления. выдан в базу данных.

Это из-за кэша 1-го уровня NHibernate, который является картой идентичности, принадлежащей сеансу.

Если вы хотите, чтобы ваш тест проверял то, что фактически было записано в базу данных, вы можете сделать это следующим образом:

session.Save(someEntity);
session.Flush(); // forces the entity to be inserted
session.Clear(); // clears the session's identity map, thus
                 // detaching someEntity from the session

var loadedEntity = session.Get<EntityType>(someEntity.Id);

// now you may compare the fields of someEntity and loadedEntity
// to verify that they were actually persisted
5 голосов
/ 29 января 2009

ISession.Update в NHibernate не фиксирует изменения в базе данных. Он используется для обновления временных экземпляров в сеансе, отличном от того, который использовался для получения экземпляра (подробности см. здесь ). Изменения отправляются в базу данных, когда сеанс сбрасывается. По умолчанию сеансы работают в режиме FlushOnCommit, что означает, что изменения объектов будут отправлены в базу данных, когда транзакция NHibernate будет зафиксирована (см. здесь для получения подробной информации о различных режимах очистки).

0 голосов
/ 02 августа 2016

Я недавно обнаружил эту же проблему.

  1. Вставленные вставки
  2. Обновления не

Проблема была в коде. Данные были проверены, если строка была изменена, затем был сопоставлен новый объект и отправлено обновление, но ничего не произошло.

Решение: Фактическая строка должна быть запрошена из базы данных, а затем изменения в C # применены к той строке, которая была отозвана. Теперь NHibernate знает, что строка изменилась, запустите save и все заработало.

  public void SaveChanges()
  {
      _session.Flush();
      _session.Transaction.Commit();
      _session.BeginTransaction();
  }
0 голосов
/ 12 января 2016

FlushMode!

Я поддерживаю приложение, которое я не написал, и выяснил трудный путь, что даже если вы используете транзакцию и звоните txn.Commit(), вы все равно можете не увидеть изменения, если ваша сессия NHibernate имеет session.FlushMode = FlushMode.Never.

Очень легко обнаружить. Установите точку останова и посмотрите на session.FlushMode. Или просто найдите все * .cs файлы для FlushMode.

0 голосов
/ 17 октября 2013

попробуйте это, может быть, я ошибаюсь, но это работает


 public void UpdateProject(Project proj)
 {
    ISessionFactory SessionFactory;

    ISession session = SessionFactory.OpenSession();

    using (ITransaction transaction = session.BeginTransaction())
    {

      session.Update(proj);
      transaction.Commit();

    }
 }

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