In NHibernate.Engine.Collections\Collection.cs there is a function
named as PrepareCollectionForUpdate. In this function NHibernate
checks the owner of the collection entity at ln 108:

bool ownerChanged = loadedPersister != currentPersister ||
                                        
!currentPersister.KeyType.IsEqual(entry.LoadedKey,
entry.CurrentKey, EntityMode.Poco);

And this will be true for my cloned entites, so NHibernate knows this
way that the owner was changed. I'm trying to find out where
NHibernate modifies the current and loaded persister for my entites.

On May 18, 7:17 pm, Fabio Maulo <[email protected]> wrote:
> In practice....If NH found a proxy, in some place, that entity was loaded
> trough NH and mean that entity need an update.
>
> 2009/5/18 Fabio Maulo <[email protected]>
>
>
>
> > There are two way to create a clone.Deep copy or shallow copy ?
>
> > 2009/5/18 domonkos <[email protected]>
>
> >> NHibernate removes entities of a many-to-one relationship from
> >> previous owner after cloning.
> >> I have a business object which holds different kind of lists:
>
> >> public class BusinessObject
> >> {
> >>        int ID{get;set;}
> >>        IList Entites{get;set;}
> >>        ...
> >> }
>
> >> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-
> >> import="false">
> >>        <class name="MainNamespace.BusinessObject, Model"
> >> table="Businessobject">
> >>                <jcs-cache usage="read-write" />
> >>                <id name="ID" type="Int32" unsaved-value="0">
> >>                        <generator class="identity" />
> >>                </id>
> >>        ...
> >>                <list name="Units" lazy="true">
> >>                        <key column="BusinessObjectID" />
> >>                        <index column="BusinessObjectIndex" />
> >>                        <one-to-many class="MainNamespace.BusinessObject,
> >> Model" />
> >>                </list>
>
> >> This is an example entity:
>
> >> public class Entity
> >> {
> >>        int ID{get;set;}
> >>        ...
> >> }
>
> >> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-
> >> import="false">
> >>        <class name="MainNamespace.Entity, Model" table="Entity">
> >>                <jcs-cache usage="read-write" />
> >>                <id name="ID" type="Int32" unsaved-value="0">
> >>                        <generator class="identity" />
> >>                </id>
> >>        ...
> >>                <many-to-one name="BusinessObject"
> >> class="MainNamespace.BusinessObject, Model" column="BusinessObjectID" /
>
> >> One noteable thing is that the entity contains a backward reference to
> >> the BusinessObject in its mapping.
>
> >> I don't use cascade because of the complexity of my lists and business
> >> workflows.
> >> The cloning process starts by creating 'new version' of business
> >> entites by removing them from the session and set their ID-s to zero
> >> to mar them as 'unsaved'.
>
> >> Here is an example of cloning a list in my business object:
>
> >> foreach(Entity entity in businessObjects)
> >> {
> >>        //New entity nothing has to be done
> >>        if(entity.ID == 0) continue;
>
> >>        //Evict old entity from session
> >>        NHibernateSession.Evict(entity);
> >>        //Mark as unsaved
> >>        entity.ID = 0;
> >> }
>
> >> The cloning process for the main business object goes by the same way
> >> which means an evict and setting its ID to 0.
> >> So after this I'll end up with an unsaved instance of my
> >> businessobject and all of my list entites.
>
> >> This is the point where I will do a 'full save' on all entites. As I
> >> can not use cascade saving I iterate through all basic entites and
> >> save them.
> >> But at first I save the whole BusinessObject.
>
> >> //Copy to a temporary list
> >> IList entites = businessObject.Entites;
> >> //Empty the list
> >> businessObject.Entites = null;
>
> >> //Save the BusinessObject
> >> NHibernateSession.Save(businessObject);
>
> >> //Saving Lists
> >> if(entites != null)
> >> {
> >>        foreach(Entity entity in entites)
> >>        {
> >>                NHibernateSession.Save(entity);
> >>        }
>
> >>        //Set back the list
> >>        businessObject.Entites = entites
> >> }
>
> >> After this point whenever a Flush is happening NHibernate will
> >> generate a query which removes all entites from the previous version
> >> of the BusinessObject.
>
> >> So for instance if the original ID of a BusinessObject was 1980 and
> >> I've set it to 0 in the clone process, the ID will be 1981 when I do
> >> the full save which is correct, but when a Flush is happening in the
> >> full save or I commit the transaction a sql query like this will also
> >> will be ran by NHibernate:
> >> exec sp_executesql N'UPDATE [Entity] SET BusinessObjectID = null,
> >> BusinessObjectIndex = null WHERE BusinessObjectID = @p0', N'@p0
> >> int',@p0 = 1980
>
> >> Where the parameter is the ID of the prevoius BusinessObject. In this
> >> case every of my entites will be removed from the previous business
> >> object.
>
> >> I don't understand why is this happening. This beahavior did not exist
> >> in the earlier version of NHibernate. I thought that evict removes the
> >> previous version of my BusinessObject from the session,
> >> I'm not sure how NHibernate 'knows' that the owner has been changed.
> >> How can this behavior fixed?
>
> > --
> > Fabio Maulo
>
> --
> Fabio Maulo
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to