简体   繁体   English

本机生成的值类型标识符在 NHibernate 中可以为空吗?

[英]Can Native generated value-type identifier be null in NHibernate?

I have a NHibernate mapping on top of a monolithic, legacy, database, and since we rolled out in production we have sporadiclly getting errors from NHibernate in about 4-8 times a day, with about 60 000 events per day processed, so the error frequency is about 0.006% - 0.013%).我在一个单一的、遗留的、数据库之上有一个 NHibernate 映射,自从我们在生产中推出以来,我们每天大约有 4-8 次从 NHibernate 收到错误,每天处理大约 60 000 个事件,所以错误频率约为 0.006% - 0.013%)。

As far as I and my colleagues have been able to determine, there's nothing that is different with these failing events/messages compared to the ones that succeed.据我和我的同事能够确定,这些失败的事件/消息与成功的事件/消息相比没有什么不同。

The error we're getting is我们得到的错误是

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)

But the identifier column is a value type (System.Int32), using Native generator.但标识符列是值类型 (System.Int32),使用 Native 生成​​器。 How can it be 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));
        });
    }
}

So, my question is really;所以,我的问题是真的; a) Why is NHibernate complain about a null identifier when the identifier is a value type (ie not nullable), ? a) 为什么当标识符是值类型(即不可为空)时,NHibernate 会抱怨空标识符,? b) Is there anything I can do about it? b) 我能做些什么吗?

I was able to isolate and reproduce the issue.我能够隔离并重现该问题。

The table in question (MyItemTable) had a index with IGNORE_DUP_KEY=ON.有问题的表 (MyItemTable) 有一个 IGNORE_DUP_KEY=ON 的索引。

And due to another issue, we we're trying to insert a near identical row twice.由于另一个问题,我们试图两次插入几乎相同的行。 The second time the insert fails with an warning, and no row is actually inserted.第二次插入失败并显示警告,实际上没有插入任何行。 So when NHibernate tries to get the generated identity, SQL Server probably returns NULL since no record was inserted.因此,当 NHibernate 尝试获取生成的标识时,由于没有插入记录,SQL Server 可能会返回 NULL。

The reason why this did not show up in any tests first was due to the fact that the database has not been versioned by tools from the start, but by manual migration.之所以没有首先出现在任何测试中,是因为数据库从一开始就没有通过工具进行版本控制,而是通过手动迁移。 Also, the index was not included when our db versioning tool scripted the legacy database.此外,当我们的数据库版本控制工具编写遗留数据库的脚本时,索引不包括在内。 The index was therefor missing in the testing environment/database generated for integration tests.因此,在为集成测试生成的测试环境/数据库中缺少该索引。 The headaches of monolithic legacy stuff...单体遗留问题的头痛...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM