Skip to content

Null reference on Merge for detached unsaved entity #2627

@pixelnix

Description

@pixelnix

Upgraded a repository to nhibernate 5.3.5 and ran into sudden null reference exceptions with a few merge operations. This example program shows the behavior, for me running it on nhibernate 5.3.5 and fluent nhibernate 3.1 throws a null reference exception on Merge(), the stack trace for which I will include below. I tried downgrading to 5.2.7 and the error went away.

using System;
using FluentNHibernate.Mapping;
using NHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate.Cfg;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            MergeTestChild child = null;
            using (var session = FluentNHibernateHelperService.OpenSession())
            {
                child = new MergeTestChild()
                {
                    Parent = session.QueryOver<MergeTestParent>().Take(1).SingleOrDefault()
                };
            }

            Console.WriteLine($"New detached instance: {child}");

            using (var session = FluentNHibernateHelperService.OpenSession())
            {
                child = session.Merge(child);
            }

            Console.WriteLine("Donezo");
            Console.ReadKey();
        }
    }

    public class MergeTestParent
    {
        public virtual int ParentId { get; set; }
        public override string ToString() => $"Parent {ParentId}";
    }
    public class MergeTestParentMap : ClassMap<MergeTestParent>
    {
        public MergeTestParentMap()
        {
            Table("merge_test_parent");
            Id(x => x.ParentId).GeneratedBy.Identity().Column("parent_id");
        }
    }

    public class MergeTestChild
    {
        public virtual int ChildId { get; set; }
        public virtual MergeTestParent Parent { get; set; }
        public override string ToString() => $"  Child {ChildId} (Parent {Parent?.ParentId})";
    }
    public class MergeTestChildMap : ClassMap<MergeTestChild>
    {
        public MergeTestChildMap()
        {
            Table("merge_test_child");
            Id(x => x.ChildId).GeneratedBy.Identity().Column("child_id");
            References(x => x.Parent, "parent_id")
                .LazyLoad(Laziness.False)
                .NotFound.Ignore()
                .Cascade.None()
                .Fetch.Join();
        }
    }

    public class FluentNHibernateHelperService
    {
        private static ISessionFactory _sessionFactory;
        
        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                    InitializeSessionFactory();

                return _sessionFactory;
            }
        }

        private static void InitializeSessionFactory()
        {
            Configuration config =
                Fluently.Configure()
                    .Database(MsSqlConfiguration.MsSql2005
                        .ConnectionString("Data Source=(local);Initial Catalog=test;Integrated Security=SSPI;Timeout=300;")
                    )
                    .Mappings(x => x.FluentMappings.AddFromAssemblyOf<ConsoleApp1.Program>())
                    .BuildConfiguration();
              _sessionFactory = config.BuildSessionFactory();
        }

        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }

        public static IStatelessSession OpenStatelessSession()
        {
            return SessionFactory.OpenStatelessSession();
        }
    }
}
Exception thrown: 'System.NullReferenceException' in NHibernate.dll
System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>ConsoleApp1.exe</AppDomain><Exception><ExceptionType>System.NullReferenceException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Object reference not set to an instance of an object.</Message><StackTrace>   at NHibernate.Type.ManyToOneType.IsNull(Object owner, ISessionImplementor session)
   at NHibernate.Type.EntityType.ResolveIdentifier(Object value, ISessionImplementor session, Object owner)
   at NHibernate.Type.EntityType.Replace(Object original, Object target, ISessionImplementor session, Object owner, IDictionary copyCache)
   at NHibernate.Type.AbstractType.Replace(Object original, Object target, ISessionImplementor session, Object owner, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
   at NHibernate.Type.TypeHelper.Replace(Object[] original, Object[] target, IType[] types, ISessionImplementor session, Object owner, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
   at NHibernate.Event.Default.DefaultMergeEventListener.CopyValues(IEntityPersister persister, Object entity, Object target, ISessionImplementor source, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
   at NHibernate.Event.Default.DefaultMergeEventListener.MergeTransientEntity(Object entity, String entityName, Object requestedId, IEventSource source, IDictionary copyCache)
   at NHibernate.Event.Default.DefaultMergeEventListener.EntityIsTransient(MergeEvent event, IDictionary copyCache)
   at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge(MergeEvent event, IDictionary copiedAlready)
   at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge(MergeEvent event)
   at NHibernate.Impl.SessionImpl.FireMerge(MergeEvent event)
   at NHibernate.Impl.SessionImpl.Merge(String entityName, Object obj)
   at NHibernate.Impl.SessionImpl.Merge[T](T entity)
   at ConsoleApp1.Program.Main(String[] args) in C:\source\repos\ConsoleApp1\Program.cs:line 27</StackTrace><ExceptionString>System.NullReferenceException: Object reference not set to an instance of an object.
   at NHibernate.Type.ManyToOneType.IsNull(Object owner, ISessionImplementor session)
   at NHibernate.Type.EntityType.ResolveIdentifier(Object value, ISessionImplementor session, Object owner)
   at NHibernate.Type.EntityType.Replace(Object original, Object target, ISessionImplementor session, Object owner, IDictionary copyCache)
   at NHibernate.Type.AbstractType.Replace(Object original, Object target, ISessionImplementor session, Object owner, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
   at NHibernate.Type.TypeHelper.Replace(Object[] original, Object[] target, IType[] types, ISessionImplementor session, Object owner, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
   at NHibernate.Event.Default.DefaultMergeEventListener.CopyValues(IEntityPersister persister, Object entity, Object target, ISessionImplementor source, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
   at NHibernate.Event.Default.DefaultMergeEventListener.MergeTransientEntity(Object entity, String entityName, Object requestedId, IEventSource source, IDictionary copyCache)
   at NHibernate.Event.Default.DefaultMergeEventListener.EntityIsTransient(MergeEvent event, IDictionary copyCache)
   at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge(MergeEvent event, IDictionary copiedAlready)
   at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge(MergeEvent event)
   at NHibernate.Impl.SessionImpl.FireMerge(MergeEvent event)
   at NHibernate.Impl.SessionImpl.Merge(String entityName, Object obj)
   at NHibernate.Impl.SessionImpl.Merge[T](T entity)
   at ConsoleApp1.Program.Main(String[] args) in C:\source\repos\ConsoleApp1\Program.cs:line 27</ExceptionString></Exception></TraceRecord>
An unhandled exception of type 'System.NullReferenceException' occurred in NHibernate.dll
Object reference not set to an instance of an object.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions