NHibernate: Сохранить, Удалить, затем Сохранить ту же сущность, создает исключение StaleStateException - PullRequest
1 голос
/ 11 января 2011

Вот мой тестовый пример:

[Test, Explicit]
public void SaveDeleteSaveThrowsTest()
{
    Produit produit = new Produit { Libelle = "Test" };

    using (ISession session = this.SessionProvider.OpenSession())
    {
        session.FlushMode = FlushMode.Auto;

        using (ITransaction transaction = session.BeginTransaction())
        {                    
            session.SaveOrUpdate(produit);
            transaction.Commit();
        }

        using (ITransaction transaction = session.BeginTransaction())
        {
            session.Delete(produit);
            transaction.Commit();
        }

        using (ITransaction transaction = session.BeginTransaction())
        {
            session.SaveOrUpdate(produit);
            Assert.Throws(typeof(StaleStateException), transaction.Commit);
        }
    }
}

Идентификаторы генерируются HiLo.

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

Есть ли способ заставить его работать? (сохранить, удалить сохранить снова тот же объект)

Ответы [ 3 ]

2 голосов
/ 11 января 2011

Разве вы не используете ленивую загрузку в отношениях многих ко *? Проблема в том, что вы сначала загружаете сущность, закрываете сессию и пытаетесь манипулировать (уже отсоединенной) сущностью. В таком случае подобъекты являются прокси, прикрепленными к закрытому сеансу. Вы должны указать NHibernate переинициализировать прокси-серверы: для каждого подобъекта вызовите NHibernateUtil.Initialize.

1 голос
/ 12 января 2011

Попробуйте Merge вместо SaveOrUpdate. Он ищет запись в базе данных (дополнительный выбор перед вставкой или обновлением). Обратите внимание, что Merge имеет возвращаемое значение, которое возвращает постоянный экземпляр, в то время как данный экземпляр все еще является временным. Вам может потребоваться очистить сеанс или создать новый сеанс, чтобы он работал.

0 голосов
/ 11 января 2011

Попробуйте вызвать Session.Save или Session.Lock для удаленного производственного объекта.

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

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