Thanks for your response. You are completely correct.

In double checking my code I realised I had left out some key bits. Please 
see below for an updated test case which demonstrates the issue.

Domain classes:

 public class House
 {
   public virtual int id { get; set; }
   public virtual Floor ground_floor { get; set; }
   public virtual IList<Floor> floors { get; set; }

   public House() {  floors = new List<Floor>(); }

   public House(int id) : this() { this.id = id; }
 }

 public class Floor
 {
   public virtual int id { get; set; }
   public virtual House house { get; set; }
   public virtual Floor_Properties props { get; set; }

   public Floor() { }

   public Floor(int id)  { this.id = id; }
 }

 Mappings:
 
 <class name="NhComponentLazyLoading.House" table="House">
 <id name="id" >
   <generator class="assigned" />
 </id>
 <many-to-one name="ground_floor" column="ground_floor_id" />
 <bag name="floors" cascade="all-delete-orphan" inverse="true">
   <key column="House_id" />
   <one-to-many class="NhComponentLazyLoading.Floor" />
 </bag>
 </class>

 <class name="NhComponentLazyLoading.Floor" table="Floor">
 <id name="id">
   <generator class="assigned" />
 </id>
 <many-to-one name="house" column="house_id" />
 <component name="props" class="NhComponentLazyLoading.Floor_Properties" 
insert="false" lazy="true">
   <property name="name" />
 </component>
 </class>

Test case:

 using (var session = NHibernateHelper.OpenSession())
 using (var tx = session.BeginTransaction())
 {
   var floor = new Floor(1);  
   session.Save(floor);
  
   var house = new House(1) { ground_floor = floor };
   floor.house = house;
 
   session.Save(house);
   tx.Commit();
 }

 using (var session = NHibernateHelper.OpenSession())
 using (var tx = session.BeginTransaction())
 {
   try
   {
     var house = session.Get<House>(1);
     house.floors.Remove(house.ground_floor);
     house.ground_floor = null;

     tx.Commit();
   }
   catch (Exception ex)
   {
     tx.Rollback();
     throw;
   }
 }

 The second commit causes the following exception.
 
 System.InvalidCastException was unhandled
  HResult=-2147467262
  Message=Unable to cast object of type 
'NHibernate.Intercept.UnfetchedLazyProperty' to type 
'NhComponentLazyLoading.Floor_Properties'.
  Source=NhComponentLazyLoading
  StackTrace:
       at (Object , GetterCallback )
       at 
NHibernate.Bytecode.Lightweight.AccessOptimizer.GetPropertyValues(Object 
target)
       at 
NHibernate.Tuple.Component.PocoComponentTuplizer.GetPropertyValues(Object 
component)
       at NHibernate.Type.ComponentType.GetPropertyValues(Object component, 
EntityMode entityMode)
       at NHibernate.Type.ComponentType.GetPropertyValues(Object component, 
ISessionImplementor session)
       at 
NHibernate.Engine.ForeignKeys.Nullifier.NullifyTransientReferences(Object 
value, IType type)
       at 
NHibernate.Engine.ForeignKeys.Nullifier.NullifyTransientReferences(Object[] 
values, IType[] types)
       at 
NHibernate.Event.Default.DefaultDeleteEventListener.DeleteEntity(IEventSource 
session, Object entity, EntityEntry entityEntry, Boolean 
isCascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
       at 
NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent 
event, ISet transientEntities)
       at NHibernate.Impl.SessionImpl.FireDelete(DeleteEvent event, ISet 
transientEntities)
       at NHibernate.Impl.SessionImpl.Delete(String entityName, Object 
child, Boolean isCascadeDeleteEnabled, ISet transientEntities)
       at NHibernate.Engine.Cascade.DeleteOrphans(String entityName, 
IPersistentCollection pc)
       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, Object anything, Boolean 
isCascadeDeleteEnabled)
       at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, 
Object parent, Object anything)
       at 
NHibernate.Event.Default.AbstractFlushingEventListener.CascadeOnFlush(IEventSource
 
session, IEntityPersister persister, Object key, Object anything)
       at 
NHibernate.Event.Default.AbstractFlushingEventListener.PrepareEntityFlushes(IEventSource
 
session)
       at 
NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent
 
event)
       at 
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
       at NHibernate.Impl.SessionImpl.Flush()
       at NHibernate.Transaction.AdoTransaction.Commit()
       ...
       
    
Please note that from inspecting the properties in the debugger the 
property house.ground_floor.prop is always null on the call to 
session.Get<House>(1).

I've also found that if I remove the floor collection mapping from the 
House class then I don't get the exception. The issue with this solution is 
that cascading deletes don't work for one-to-one or effective one-to-one 
relationships in the current version of NHibernate. Therefore I need the 
collection mapping to be able to delete child associations without 
resorting to session.Delete.

The only solution I have found is to remove lazy="true" from the component 
mapping.

Any help would be gratefully appreciated.

Thanks

Michael

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/nhusers?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to