nhibernate-core icon indicating copy to clipboard operation
nhibernate-core copied to clipboard

NullReferenceException when Merge(obj) is called

Open FouadSsitou opened this issue 3 years ago • 4 comments

A NullReferenceException is thrown on a Parent/child relation.

If there is a new entry in the Child collection Merge throws NullReferenceException.

It fails because the new entity does not have any persister.

image

Stacktrace:
   at NHibernate.Engine.StatefulPersistenceContext.ProxyFor(Object impl)
   at NHibernate.Type.ComponentType.Instantiate(Object parent, ISessionImplementor session)
   at NHibernate.Type.ComponentType.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.Impl.SessionImpl.FireMerge(IDictionary copiedAlready, MergeEvent event)
   at NHibernate.Impl.SessionImpl.Merge(String entityName, Object obj, IDictionary copiedAlready)
   at NHibernate.Engine.CascadingAction.MergeCascadingAction.Cascade(IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled)
   at NHibernate.Engine.Cascade.CascadeToOne(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
   at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
   at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, String propertyName, Object anything, Boolean isCascadeDeleteEnabled)
   at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, Object child, CollectionType collectionType, CascadeStyle style, IType elemType, Object anything, Boolean isCascadeDeleteEnabled)
   at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object child, CascadeStyle style, Object anything, CollectionType type)
   at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
   at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, String propertyName, Object anything, Boolean isCascadeDeleteEnabled)
   at NHibernate.Engine.Cascade.CascadeComponent(Object parent, Object child, IAbstractComponentType componentType, String componentPropertyName, Object anything)
   at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, String propertyName, Object anything, Boolean isCascadeDeleteEnabled)
   at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
   at NHibernate.Event.Default.DefaultMergeEventListener.CascadeOnMerge(IEventSource source, IEntityPersister persister, Object entity, IDictionary copyCache)
   at NHibernate.Event.Default.DefaultMergeEventListener.EntityIsDetached(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(Object obj)

Parent Mapping file:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">

	<class name="Boss.Model.DecisionMakerInformation, Boss.Model" table="Company">
		<id name="myDatabaseId" type="Int64" column="CompanyID" unsaved-value="0" access="field">
			<generator class="identity"/>
		</id>

		<component name="myDecisionMakers" class="Boss.Model.DecisionMakerList, Boss.Model" access="field">
			<parent name="Parent"  />
			<bag name="myList" table="JobAppointment" access="field" order-by="JobAppointmentID" cascade="all-delete-orphan" inverse="true">
				<key column="CompanyID"/>
				<one-to-many class="Boss.Model.DecisionMaker, Boss.Model" />
			</bag>
		</component>
	</class>
</hibernate-mapping>

Child mapping file:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">

	<class name="Boss.Model.DecisionMaker, Boss.Model" table="JobAppointment">
		<id name="myDatabaseId" type="Int64" column="JobAppointmentID" unsaved-value="0" access="field">
			<generator class="identity"/>
		</id>
		<version name="myDatabaseVersion" column="Version" access="field"/>
		
		<many-to-one access="field" class="Boss.Model.DecisionMakerInformation, Boss.Model" column="CompanyID" name="myParent" not-null="true"/>
		
		<!--<many-to-one name="myCompany" class="Boss.Model.CompanyInformation, Boss.Model" column="CompanyID" access="field"/>-->
		<many-to-one name="myPerson" class="Boss.Model.Person, Boss.Model" column="PersonID" access="field" />

		<property name="myIsPartOfManagement" type="Boolean" column="Management" access="field"/>
		<many-to-one name="myTitle" class="Boss.Model.TitleType, Boss.Model" column="TitleID" access="field"/>
		<many-to-one name="myBoardOfDirectorsType" class="Boss.Model.BoardOfDirectorsType, Boss.Model" column="BoardOfDirectorsID" access="field"/>
		<property name="myBoardOfDirectorsAccessionDate" type="Timestamp" column="BoardOfDirectorsAccessionDate" access="field"/>
		<property name="myBoardOfDirectorsResignationDate" type="Timestamp" column="BoardOfDirectorsResignationDate" access="field"/>
		<property name="myManagementAccessionDate" type="Timestamp" column="ManagementAccessionDate" access="field"/>
		<property name="myManagementResignationDate" type="Timestamp" column="ManagementResignationDate" access="field"/>

		<property name="myPhoneNumber" column="PhoneNumber" access="field" type="String"/>
		<property name="myFaxNumber" column="FaxNumber" access="field" type="String"/>
		<property name="myMobilePhoneNumber" column="MobilePhoneNumber" access="field" type="String"/>
		<property name="myEmail" column="Email" access="field" type="String"/>
		<!-- 2009-10-16 RJ_Regtid_Total - boolean for marking decisionmakers imported via Regtid/Total import (check this bit, to see what needs to be deleted after import of full dump from E&S) -->
		<property name="myDataImportMarker" column="DataImportMarker" access="field" type="Boolean"/>
    <!-- 2014-01-31 BB: -->
    <many-to-one name="myManagementType" class="Boss.Model.ManagementType, Boss.Model" column="ManagementID" access="field"/>

		<component name="myFieldOfResponsibilityList" class="Boss.Model.FieldOfResponsibilityList, Boss.Model" access="field">
			<parent name="Parent" />
			<bag name="myList" table="JobAppointment_FieldOfResponsibility_rel" access="field" order-by="JobAppointment_FieldOfResponsibility_relID" cascade="all-delete-orphan" inverse="true">
				<key column="JobAppointmentID"/>
				<one-to-many class="Boss.Model.FieldOfResponsibility, Boss.Model" />
			</bag>
		</component>

		<component name="myAuditInformation" class="Boss.Model.AuditInformation, Boss.Model" access="field">
			<property name="myUtcTimestamp" type="Timestamp" column="AuditDate" access="field"/>
			<many-to-one name="myInformationSource" class="Boss.Model.InformationSource, Boss.Model" column="AuditSourceID" access="field"/>
			<many-to-one name="myUser" class="Boss.Model.User, Boss.Model" column="AuditUserID" access="field"/>
		</component>
	</class>

</hibernate-mapping>

FouadSsitou avatar Jul 28 '22 11:07 FouadSsitou

I found out that if the component myFieldOfResponsibilityList is set to null then it works.

But if I add an element then we are back to square one.

FouadSsitou avatar Jul 28 '22 20:07 FouadSsitou

Nhibernate 5.3.12

@FouadSsitou does it happen on other versions?

hazzik avatar Jul 28 '22 21:07 hazzik

Nhibernate 5.3.12

@FouadSsitou does it happen on other versions?

Yes it happens from version 3 to the newest version.

FouadSsitou avatar Jul 28 '22 22:07 FouadSsitou

Can you please show code to demonstrate this?

hazzik avatar Feb 28 '23 04:02 hazzik