NHibernate.AssertionFailure: null identifier

2019-06-22 11:56发布

Before I kick my computer in to next week...

I've checked out every other question about this, but none of them have the solution. I've stripped this code right back, but it's still not working.

I'm getting this error when saving an object: NHibernate.AssertionFailure: null identifier

This is my mapping file:

public class OrderMap : BaseMap<Order>
{
    public SalesOrderMap()
    {
        Id(x => x.Id).Column("OrderId");
    }
}

This is the entity:

public class Order
{
    public virtual int Id { get; protected set; }
}

This is my test code:

Order order = new Order();
ISession session = SessionFactory.GetCurrentSession();
session.SaveOrUpdate(order); <----EXCEPTION ON THIS LINE
session.Flush();

And then bang...it breaks with

[AssertionFailure: null identifier]
  NHibernate.Engine.EntityKey..ctor(Object identifier, String rootEntityName, String entityName, IType identifierType, Boolean batchLoadable, ISessionFactoryImplementor factory, EntityMode entityMode) +135
   NHibernate.Engine.EntityKey..ctor(Object id, IEntityPersister persister, EntityMode entityMode) +70
   NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) +545
   NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) +322
   NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) +130
   NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) +27
   NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event) +63
   NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event) +89
   NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event) +188
   NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent event) +259
   NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj) +256

if anyone's interested, this is how the session factory is built:

ControllerSource.SessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008.ConnectionString(DataConfig.ConnectionString))
                .Mappings(x => x.FluentMappings.Add(typeof (OrderMap)))
                .ExposeConfiguration(c =>{
                                             c.SetProperty("generate_statistics", "false");
                                             c.SetProperty("current_session_context_class", contextClass);
                                             c.SetProperty("cache.use_second_level_cache", "false");
                                             c.SetProperty("cache.use_query_cache", "false");
                                             c.SetProperty("connection.release_mode", "on_close");
                })
                .BuildSessionFactory();

3条回答
何必那么认真
2楼-- · 2019-06-22 12:35

The default generator is Native which will in turn use Identity for SQL Server 2008. My bet is that you don't have identity specified on the column in the table definition.

查看更多
唯我独甜
3楼-- · 2019-06-22 12:41

You need to either assign your entitity an id when trying to create a new one or specify how it is generated in the mapping file. Change your mapping to:

Id(x => x.Id).Column("OrderId").GeneratedBy.Identity();
查看更多
beautiful°
4楼-- · 2019-06-22 12:58

Check that your table doesn't have a trigger that is interfering with the INSERT, or perhaps calling a stored procedure on insert.

When NHibernate inserts the entity, it will ask the database for the auto-generated primary key of the new entity.

INSERT INTO [Order] (MyProperty) VALUES (@p0); select SCOPE_IDENTITY()

Note the select SCOPE_IDENTITY() call.

If SCOPE_IDENTITY returns NULL, then you'll get the NHibernate.AssertionFailure: null identifier exception.

As an example, an "INSTEAD OF INSERT" trigger will make SCOPE_IDENTITY return null, and trigger the NHibernate assertion.

If you find a trigger interfering, you can troubleshoot whether it is the actual problem by temporarily disabling it. For the long term, you can then decide whether to get rid of the trigger entirely if it's no longer needed.

Alternatively, you can wrap your insert in a transaction; then disable the trigger before the insert, do the actual save/insert of the entity, then re-enable the trigger and commit the transaction.

查看更多
登录 后发表回答