在NHibernate中Native可以生成值类型标识符吗?

时间:2013-11-01 14:10:18

标签: c# nhibernate fluent-nhibernate

我在一个单一的遗留数据库之上有一个NHibernate映射,自从我们在生产中推出以来,我们每天大约有4-8次从NHibernate偶尔得到错误,每天处理大约60,000个事件,所以误差率约为0.006% - 0.013%。

就我和我的同事所能确定的而言,与那些成功的事件相比,这些失败的事件/消息没有什么不同。

我们得到的错误是

NHibernate.AssertionFailure: null identifier
at NHibernate.Engine.EntityKey..ctor(Object identifier, String rootEntityName, String entityName, IType identifierType, Boolean batchLoadable, ISessionFactoryImplementor factory, EntityMode entityMode)
at NHibernate.Engine.EntityKey..ctor(Object id, IEntityPersister persister, EntityMode entityMode)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)

但标识符列是一个值类型(System.Int32),使用Native生成器。 怎么会是null?

public class MyItem {
   public int MyItemId { get; set; }
}

public class MyItemMap : ClassMapping<MyItem>
{
    public MyItemMap ()
    {
        Table("MyItemTable");

        Id(m => m.MyItemId, x =>
        {
            x.Column("MyItem_ID");
            x.Generator(Generators.Native);
            x.UnsavedValue(default(int));
        });
    }
}

所以,我的问题确实存在; a)当标识符是值类型(即不可为空)时,为什么NHibernate会抱怨空标识符? b)我能做些什么吗?

1 个答案:

答案 0 :(得分:0)

我能够分离并重现这个问题。

有问题的表(MyItemTable)有一个IGNORE_DUP_KEY = ON的索引。

由于另一个问题,我们正在尝试两次插入几乎相同的行。 第二次插入失败并显示警告,并且实际上没有插入任何行。 因此,当NHibernate尝试获取生成的标识时,SQL Server可能会返回NULL,因为没有插入记录。

首先没有出现在任何测试中的原因是因为数据库从一开始就没有通过工具进行版本化,而是通过手动迁移。此外,当我们的db版本控制工具编写旧数据库脚本时,未包含该索引。 因此,在为集成测试生成的测试环境/数据库中缺少索引。 单片遗留物的头痛......