I posted this problem previously, but have been unable to solve it. I am wondering if this is a bug in NHibernate:
I have 2 classes that form a parent-child relationship. I am trying to move all children from one instance of a parent to another parent instance, but I'm getting an ObjectDeletedException.
Hibernate version: 1.0.2
Mapping documents:
I have a Patient class and a PatientProfile class. The Patient has a set of PatientProfiles, mapped as a parent-child relationship, as shown:
Code:
<class name="Patient" proxy="Patient" table="Patient_">
<id name="OID" column="OID_" type="Int64">
<generator class="hilo">
<param name="max_lo">100</param>
</generator>
</id>
<version name="Version" column="Version_"/>
<set name="Profiles" lazy="true" inverse="true" cascade="all-delete-orphan" access="nosetter.camelcase-underscore">
<key column="PatientOID_"/>
<one-to-many class="PatientProfile"/>
</set>
</class>
<class name="PatientProfile" proxy="PatientProfile" table="PatientProfile_">
<id name="OID" column="OID_" type="Int64">
<generator class="hilo">
<param name="max_lo">100</param>
</generator>
</id>
<version name="Version" column="Version_"/>
<many-to-one name="Patient" class="Patient" column="PatientOID_" not-null="true" fetch="join"/>
</class>
Code between sessionFactory.openSession() and session.close():
The purpose of the code is to move all PatientProfiles from one Patient to another Patient, and delete the patient with no profiles, as shown here:
Code:
using (ITransaction trans = session.BeginTransaction())
{
Patient a = (Patient)session.Load(typeof(Patient), idA);
Patient b = (Patient)session.Load(typeof(Patient), idB);
// copy patient b profiles into temp arraylist
ArrayList bProfiles = new ArrayList(b.Profiles);
// Move profiles from patient b to patient a
foreach (PatientProfile bProfile in bProfiles)
{
if (bProfile.Patient != null)
{
b.Profiles.Remove(bProfile);
}
bProfile.Patient = a;
a.Profiles.Add(bProfile);
}
session.Delete(b);
trans.Commit();
}
Full stack trace of any exception that occurs:
Code:
A first chance exception of type 'NHibernate.ObjectDeletedException' occurred 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>HibernateTest.vshost.exe</AppDomain><Exception><ExceptionType>NHibernate.ObjectDeletedException, NHibernate, Version=1.0.2.0, Culture=neutral, PublicKeyToken=154fdcb44c4484fc</ExceptionType><Message>deleted object would be re-saved by cascade (remove deleted object from associations): 405, of class: HibernateTest.PatientProfile</Message><StackTrace> at NHibernate.Impl.SessionImpl.ForceFlush(EntityEntry e)
at NHibernate.Impl.SessionImpl.Save(Object obj)
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)
at NHibernate.Engine.Cascades.CascadingAction.ActionSaveUpdateClass.Cascade(ISessionImplementor session, Object child, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, Object child, IType type, CascadingAction action, CascadeStyle style, CascadePoint cascadeTo, Object anything)
at NHibernate.Engine.Cascades.CascadeCollection(CascadingAction action, CascadeStyle style, PersistentCollectionType collectionType, IType elemType, Object child, CascadePoint cascadeVia, ISessionImplementor session, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, Object child, IType type, CascadingAction action, CascadeStyle style, CascadePoint cascadeTo, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, IClassPersister persister, Object parent, CascadingAction action, CascadePoint cascadeTo, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, IClassPersister persister, Object parent, CascadingAction action, CascadePoint cascadeTo)
at NHibernate.Impl.SessionImpl.PreFlushEntities()
at NHibernate.Impl.SessionImpl.FlushEverything()
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at HibernateTest.Program.Main(String[] args) in
Interestingly, if I remove the line
Code:
session.Delete(b);
from the above code, no exception is thrown, but NHibernate generates incorrect SQL:
Code:
NHibernate: UPDATE ris4.dbo.Patient_ SET Version_ = @p0 WHERE OID_ = @p1 AND Version_ = @p2
@p0 = '9'
@p1 = '102'
@p2 = '8'
NHibernate: UPDATE ris4.dbo.Patient_ SET Version_ = @p0 WHERE OID_ = @p1 AND Version_ = @p2
@p0 = '1'
@p1 = '304'
@p2 = '0'
NHibernate: DELETE FROM ris4.dbo.PatientProfile_ WHERE OID_ = @p0 AND Version_ = @p1
@p0 = '405'
@p1 = '0'
The first 2 statements simply update the Version of the Patients, which is correct. However, the last statement should just update the foreign key reference of the PatientProfile. Why does it delete it?