NHibernate.AssertionFailure: нулевой идентификатор в записи APP.Domain.Entity.EntityName (не сбрасывать сеанс после возникновения исключения)

Я пытаюсь вставить в таблицу столбец Identity Id, но получаю исключение;

NHibernate.AssertionFailure: нулевой идентификатор в записи APP.Domain.Entity.EntityName (не сбрасывать сеанс после возникновения исключения)

Я использовал session.Flush() как в точке фиксации, так и в точке отката транзакции, и после этого все, казалось, работало ненадолго, затем исключение снова запустилось.

using (var tranx = _session.BeginTransaction())
{
        try
        {       
                Entity entityName = new Entity();
                entityName.propert1 = propert1.value;
                entityName.propert2 = propert2.value;
                entityName.propert3 = propert3.value;
                entityName.propert4 = propert4.value;
                _session.Save(entityName);

                .....
                other transactions
                .....

                tranx.Commit();
                _session.Flush();
        }
        catch (Exception ex)
        {
                tranx.Rollback();
                _session.Flush();              
        }
}

Я ожидаю, что в таблицу БД будет вставлена ​​запись и автоматически сгенерирован идентификатор для нее, но вместо этого я получаю журнал;

Всего 1 ответ


Ниже код в вашем вопросе:

_session.Save(entityName);

.....
other transactions
.....

tranx.Commit();
_session.Flush();

похоже, что вы делаете несколько действий в одной транзакции - ОК; это называется Единица работы.

Затем в блоке catch вы откатываете транзакцию (отменяете UoW), как показано ниже:

catch (Exception ex)
{
    tranx.Rollback();//<--This is OK
    _session.Flush();//<--Why this? Remove this line.
}

Это тоже нормально. Но тогда вы ISession . Почему так?

Ваш использующий блок правильно расположит сеанс. Я не вижу никакого преимущества сброса сессии в блоке catch . Вы должны удалить эту строку.

Исключение, которое вы упомянули в вопросе:

NHibernate.AssertionFailure: нулевой идентификатор в записи APP.Domain.Entity.EntityName (не сбрасывать сеанс после возникновения исключения)

не является настоящим исключением. До этого произошло настоящее исключение. Вы используете исключение в блоке catch . Лучшим способом является модификация блока блока catch для обработки (регистрировать может быть исключение и повторно генерировать (с помощью throw; исходное исключение)) исключение. Если вы не можете обработать исключение, просто удалите блоки try-catch и оставьте исключение снаружи; вызывающий должен справиться с этим. Ваш блокирующий блок в любом случае ISession - он также откатит транзакцию, если не зафиксирован.

Я ожидаю, что запись будет вставлена ​​в таблицу БД и автоматически сгенерирован идентификатор для нее, но вместо этого я получаю журнал

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

Почему не Flush после исключения NHibernate?

Unit Of Work - очень сложная система. Он отслеживает изменения для всех загруженных объектов. NHibernate делает отличные вещи, чтобы сохранить это в памяти копий объектов в соответствии с основной СУБД. Flush (или другие способы автоматической очистки) обновит RDBMS с изменениями в памяти. Когда выдается исключение NHibernate, это не гарантирует, что это состояние больше не находится в согласованном состоянии. Именно поэтому NHibernate рекомендует избавиться от сессии и начать с нуля.


Есть идеи?

10000