Try to create a failing NUnit test and create a new issue (improvement) in
our JIRA.Thanks.

2009/3/9 Germán Schuager <[email protected]>

> Fabio, I've made up the Cat class only to show my point: session.Merge is
> accessing properties of instances in invalid state when it is not needed.
>
> I do have the real use-case and I assure you that it makes a lot more sense
> than the cat ;) only that it is very complex to present it here...
>
> The solution was simple. I just added this to the Num getter:
>
> if (state != null) return 0;
>
> but this was only to please session.Merge, and I think that NH could be
> improved by not requiring me to do that.
>
> If I came up with something more "real" than the Cat I will follow up.
>
> Thanks for your time.
>
>
>
>
> On Mon, Mar 9, 2009 at 6:39 PM, Fabio Maulo <[email protected]> wrote:
>
>> Ah... German... try to recreate the situation out-side the code of the
>> application; I'm sure you will find the solution or at least you can send us
>> a real use-case with a real class and a real mapping.
>>
>> 2009/3/9 Fabio Maulo <[email protected]>
>>
>> so.. in a property getter you are accessing to a Relationship loaded using
>>> lazy-loading, inside the same class... and all to have a unnormalized
>>> property.interesting and discouraged approach.
>>>
>>> Inside the getter you should check if "state" is a proxy and in that case
>>> you should initialize it (the dyn-proxy don't work inside the instance)
>>>
>>> Another possibility is fetch="join" to load "state" immediately.
>>>
>>> Your existing code are working only under some very specific condition:
>>> it work only if you access to the property "State" before access to the
>>> property "Num" from some place outside the class instance.
>>> To be clear, try this in a fresh session:
>>> var c = session.Get<Cat>(id);
>>> Assert.That(c.Num, Is.Not.EqualTo(0));
>>>
>>>
>>>
>>> 2009/3/9 Germán Schuager <[email protected]>
>>>
>>>> My actual model is somewhat more complex than this:
>>>>
>>>> public interface INum
>>>> {
>>>>    int Num { get; }
>>>> }
>>>>
>>>> public class Cat : Entity, INum
>>>> {
>>>>    private State state;
>>>>
>>>>    protected Cat() { }
>>>>
>>>>    public Cat(State state)
>>>>    {
>>>>       this.state = state;
>>>>    }
>>>>
>>>>    public virtual State State { get { return state; } }
>>>>
>>>>    public virtual int Num { get { return state.Num; } }
>>>> }
>>>>
>>>> <?xml version="1.0" encoding="utf-8"?>
>>>> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
>>>> assembly="MyAssembly" namespace="MyNamespace">
>>>>   <class name="Cat" table="Cats">
>>>>     <id name="ID" column="CatID" type="Int32">
>>>>       <generator class="hilo" />
>>>>     </id>
>>>>     <many-to-one name="State" access="field.camelcase" />
>>>>     <property name="Num" access="readonly" />
>>>>   </class>
>>>> </hibernate-mapping>
>>>>
>>>>
>>>> On Mon, Mar 9, 2009 at 6:05 PM, Fabio Maulo <[email protected]>wrote:
>>>>
>>>>> Mapping please.
>>>>>
>>>>>
>>>>> 2009/3/9 Germán Schuager <[email protected]>
>>>>>
>>>>>> inline
>>>>>>
>>>>>> On Mon, Mar 9, 2009 at 5:11 PM, Fabio Maulo <[email protected]>wrote:
>>>>>>
>>>>>>> The fact is that the Merge need to read the state from DB but with
>>>>>>> its result in the persistent class (not from DataReader).
>>>>>>
>>>>>>
>>>>>> I think that I understand. That is the case of merging a detached
>>>>>> entity, but when merging a new transient entity that it is not in the DB
>>>>>> then NH does not need to do this, does it?
>>>>>>
>>>>>>
>>>>>>> BTW I don't understand how you can work with that entity... NH use
>>>>>>> the parameterless ctor not only for Merge but even when you use
>>>>>>> session.Get<T>(id).
>>>>>>>
>>>>>>
>>>>>> Yes, but when using session.Get, it creates the new entity and WRITE
>>>>>> its properties (*), on the other hand when using session.Merge it creates
>>>>>> the entity and READ its properties.
>>>>>>
>>>>>>
>>>>>>>  In case of Get/Load who are injecting the State instance ?
>>>>>>>
>>>>>>
>>>>>> NH is assigning the state field. I don't understand what you mean.
>>>>>>
>>>>>>
>>>>>>
>>>>>> (*) here the problem could be that NH tries to set Num before State,
>>>>>> but this is due to me trying to simplify my domain; just suppose that Num
>>>>>> doesn't have a setter and is mapped using access="readonly"
>>>>>>
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> 2009/3/9 Germán Schuager <[email protected]>
>>>>>>>
>>>>>>>> Thanks Fabio, I will take a look at what a tuplizer is :), but I
>>>>>>>> don't see why NH needs to access the properties of a newly created 
>>>>>>>> object
>>>>>>>> just to overwrite them with the transient instance properties' values.
>>>>>>>>
>>>>>>>> I'm browsing the NH source to trying to find out but it is complex
>>>>>>>> beast...
>>>>>>>>
>>>>>>>> It seems that this drags from the fact that both EntityIsTransient
>>>>>>>> and EntityIsDetached are using the same method (CopyValues) to update 
>>>>>>>> the
>>>>>>>> properties of the resulting persistent entity. Do you see room for
>>>>>>>> improvement here or I should just move on?
>>>>>>>>
>>>>>>>> Thanks again.
>>>>>>>>
>>>>>>>>
>>>>>>>> On Mon, Mar 9, 2009 at 4:27 PM, Fabio Maulo 
>>>>>>>> <[email protected]>wrote:
>>>>>>>>
>>>>>>>>> Ah.. sorry.. in Merge sure it access to the getter... sorryIf you
>>>>>>>>> need a certain ctor you should implement your own tuplizer (I don't 
>>>>>>>>> know
>>>>>>>>> where you will find the State instance but it is another matter).
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> 2009/3/9 Germán Schuager <[email protected]>
>>>>>>>>>
>>>>>>>>>> I've tried it. It does access the getters when merging an entity
>>>>>>>>>> in the method CopyValues of DefaultMergeEventListener.cs
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Event/Default/DefaultMergeEventListener.cs
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Mon, Mar 9, 2009 at 3:14 PM, Fabio Maulo <[email protected]
>>>>>>>>>> > wrote:
>>>>>>>>>>
>>>>>>>>>>> NH don't access to the getter during object creation. Try it.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> 2009/3/9 Germán Schuager <[email protected]>
>>>>>>>>>>>
>>>>>>>>>>>> Hi Fabio,
>>>>>>>>>>>>
>>>>>>>>>>>> Num is a persistent property, and I have several entities that
>>>>>>>>>>>> implement INum; in this case Cat is delegating its actual 
>>>>>>>>>>>> implementation to
>>>>>>>>>>>> its private field "state".
>>>>>>>>>>>>
>>>>>>>>>>>> I don't think that a nosetter access for Num would solve the
>>>>>>>>>>>> problem because the exception would be generated anyway (when 
>>>>>>>>>>>> accessing the
>>>>>>>>>>>> getter of Num for the newly instantiated Cat, the persistent one, 
>>>>>>>>>>>> which has
>>>>>>>>>>>> state == null yet).
>>>>>>>>>>>>
>>>>>>>>>>>> And with the readonly accesor it would also be the same.
>>>>>>>>>>>>
>>>>>>>>>>>> The problem here is that NH is trying to read Num from an entity
>>>>>>>>>>>> that is in an invalid state in order to compare this value with the
>>>>>>>>>>>> transient one that I'm trying to merge, to determine if it should 
>>>>>>>>>>>> be copied
>>>>>>>>>>>> or not. (At least I think this is the problem)
>>>>>>>>>>>>
>>>>>>>>>>>> Does this make sense?
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On Mon, Mar 9, 2009 at 1:51 PM, Fabio Maulo <
>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> If Num is a persistent property you should use- a field only
>>>>>>>>>>>>> to make NH happy (you don't need to use it)
>>>>>>>>>>>>> - Num access="nosetter.camelcase"... if I well remember we have
>>>>>>>>>>>>> another accessor in NH2.1 access="read-only"
>>>>>>>>>>>>>
>>>>>>>>>>>>> 2009/3/9 Germán Schuager <[email protected]>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Hi,
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I want to do a merge of a transient object which some of its
>>>>>>>>>>>>>> properties are assigned with detached objects, in order to get a 
>>>>>>>>>>>>>> persistent
>>>>>>>>>>>>>> object with all its properties assigned with persistent 
>>>>>>>>>>>>>> instances (using
>>>>>>>>>>>>>> cascade="merge"). Is this the correct usage scenario for merge?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Here is a sample entity:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> public interface INum
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>>    int Num { get; }
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> public class Cat : Entity, INum
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>>    private State state;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>    protected Cat() { }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>    public Cat(State state)
>>>>>>>>>>>>>>    {
>>>>>>>>>>>>>>       this.state = state;
>>>>>>>>>>>>>>    }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>    public State State { get { return state; } }  <--- mapped
>>>>>>>>>>>>>> using access="field.camelcase"
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>    public int Num {
>>>>>>>>>>>>>>       get { return state.Num; }
>>>>>>>>>>>>>>       set { state.Num = value; }
>>>>>>>>>>>>>>    }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The problem that I'm facing is that Merge is trying to read
>>>>>>>>>>>>>> the Num property from a Cat created using the protected 
>>>>>>>>>>>>>> constructor (the
>>>>>>>>>>>>>> persistent instance?) before assigning its "state" field, thus 
>>>>>>>>>>>>>> throwing a
>>>>>>>>>>>>>> NullReferenceException in the getter.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> A simple solution would be to add a check to verify that state
>>>>>>>>>>>>>> != null in the getter, but that would be only to support NH 
>>>>>>>>>>>>>> functionality
>>>>>>>>>>>>>> and it would have nothing to do with my domain.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Do I need to add the check for state != null?
>>>>>>>>>>>>>> Can NH be improve to handle this situation?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Regards.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> --
>>>>>>>>>>>>> Fabio Maulo
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> Fabio Maulo
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Fabio Maulo
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Fabio Maulo
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Fabio Maulo
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>> --
>>> Fabio Maulo
>>>
>>
>>
>>
>> --
>> 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