I have a 'Load' Object with a one-to-many inverse relationship (bag) containing 'Pickup' Objects. Both have been created outside of the session (on a rich client). Every 'Pickup' requires a 'Load'.
The following fails to work
Code:
'Outside of the session
'After creating a new load and pickup
pickup.load = load
load.Pickups.Add(pickup)
'In the session
session.SaveAndUpdateCopy(load) 'This fails
session.SaveAndUpdateCopy(pickup)
The exception is:
Code:
WasteLinkEntityTest.IntegrationTest.DataAccessBroker.NHibernateScopeTest.TestCollectionInverseSave : NHibernate.TransientObjectException : object references an unsaved transient instance - save the transient instance before flushing: WasteLinkWebService.Entity.Transport.Pickup
at NHibernate.Impl.SessionImpl.ThrowTransientObjectException(Object obj)
at NHibernate.Impl.SessionImpl.GetEntityIdentifierIfNotUnsaved(Object obj)
at NHibernate.Type.EntityType.GetIdentifier(Object value, ISessionImplementor session)
at NHibernate.Type.EntityType.Copy(Object original, Object target, ISessionImplementor session, Object owner, IDictionary copyCache)
at NHibernate.Type.PersistentCollectionType.CopyElement(ICollectionPersister persister, Object element, ISessionImplementor session, Object owner, IDictionary copiedAlready)
at NHibernate.Type.PersistentCollectionType.Copy(Object original, Object target, ISessionImplementor session, Object owner, IDictionary copiedAlready)
at NHibernate.Type.TypeFactory.Copy(Object[] original, Object[] target, IType[] types, ISessionImplementor session, Object owner, IDictionary copiedAlready)
at NHibernate.Impl.SessionImpl.DoCopy(Object obj, Object id, IDictionary copiedAlready)
at NHibernate.Impl.SessionImpl.SaveOrUpdateCopy(Object obj)
at WasteLinkWebService.DataAccess.DatabaseBroker.SaveOrUpdate(Object obj) in c:\inetpub\wwwroot\WasteLinkWebService\DataAccess\DatabaseBroker.vb:line 103
Now it works fine if SaveAndUpdateCopy is replaced with SaveAndUpdate. SaveAndUpdate simply ignores the collection since it's an inverse. Obviously the copy has issues copying the transient objects, but because the collection is an inverse I can't see why it matters whether the collection contains persistent or transient objects.
At the moment I'm not sure if this is simply an inherit limitation imposed when using the copy version, or if this is an actual issue.
This problem can be worked around by copying the transient collection elements to a temporary collection, but it's very tedious and breaks the encapsulation model. Moreso when there are multiple levels of one-to-manys. We've settled on including a transientBlahCollection on the objects but that's a horrible design smell.