NHibernate.AssertionFailure:APP.Domain.Entity.EntityName条目中的ID为null(发生异常后不要刷新Session)

时间:2019-05-15 11:59:12

标签: c# nhibernate

我试图插入具有Identity Id列的表,但是我一直收到异常;

  

NHibernate.AssertionFailure:APP.Domain.Entity.EntityName条目中的ID为null(在发生异常后不要刷新Session)

我在事务的提交点和回滚点都使用了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();              
        }
}

我希望在数据库表中插入一条记录,并为其自动生成一个ID,但我却得到了日志;

1 个答案:

答案 0 :(得分:0)

从下面的问题代码中:

_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。为什么呢?

您的using块将正确处理会话。我看不到在catch块中刷新会话有任何好处。您应该删除该行。

您提到的异常:

  

NHibernate.AssertionFailure:APP.Domain.Entity.EntityName条目中的ID为null(在发生异常后不要刷新Session)

不是真正的例外。真正的例外发生在那之前。您正在catch块中使用异常。更好的方法是将catch块修改为 handle (记录异常可能并重新抛出(带有throw;原始异常))该异常。如果您无法处理该异常,则只需删除try-catch块,然后将该异常扔到外面即可;来电者应处理。无论如何,您的using块都会处置ISession -如果未提交,也会回滚事务。

  

我希望在数据库表中插入一条记录,并为其自动生成一个ID,但我却得到了日志

如上所述,您真正的例外正在被静默消耗。因此,我们无法告诉您为什么这种情况没有发生。实施上述措施,您将自己了解原因。

NHibernate异常后为什么不Flush

工作单元是非常复杂的系统。它跟踪所有已加载实体的更改。 NHibernate做了大量工作,以使该内存实体副本与基础RDBMS保持一致。 Flush(或其他自动刷新方式)将使用内存更改来更新RDBMS。抛出NHibernate异常时,不能保证此状态不再处于一致状态。这就是NHibernate建议处置会话并从头开始的原因。