NHibernate.AssertionFailure: null identifier
Asked Answered
S

3

5

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();
Soma answered 15/11, 2011 at 15:2 Comment(5)
Can you post the create script for the order table?Ringdove
It's currently just a table with the field in, auto increment, int, not nullableSoma
(I think I've been a bit of a pillock........)Soma
How about showing your SessionFactory.GetCurrentSessionRingdove
In my similiar case this post was helpful [AssertionFailure: “null identifier” - FluentNH + SQLServerCE][1] [1]: #2362230Babara
S
16

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.

Sweven answered 15/11, 2011 at 16:11 Comment(1)
Thats the correct explanation. Someone should accept this as the answer.Interstellar
W
3

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.

Waring answered 24/2, 2015 at 3:33 Comment(1)
You can be helpful even when you're not in the office David!Vestavestal
M
1

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();
Merc answered 15/11, 2011 at 15:18 Comment(2)
I believe "Identity" is the default for that value...unfortunately that didn't workSoma
@Soma - remove 'protected' from set in orderid propertyMerc

© 2022 - 2024 — McMap. All rights reserved.