It will assign the ID first, I think

On Sat, Feb 21, 2009 at 3:41 PM, Germán Schuager <[email protected]>wrote:

> Thanks, that solved the problem.
>
> I agree that once an object is initialized the value returned by
> GetHashCode should not change (actually Name has a private setter and is
> only assigned in one of the constructors or by NH when loading the entity),
> but here NH is forcing a GetHashCode evaluation (by using it as a dictionary
> key) before it assigns all the object's properties. This behavior is
> different than the one used when the dictionary is lazy-loaded... I just
> want to confirm that this behavior is by-design.
>
> Anyway, I guess the documentation (
> http://www.nhforge.org/doc/nh/en/index.html#persistent-classes-equalshashcode)
> would welcome an update :)
>
>
> On Sat, Feb 21, 2009 at 4:19 PM, Fabio Maulo <[email protected]> wrote:
>
>>  private int? requestedHashCode;
>> public override int GetHashCode()
>> {
>>  if (!requestedHashCode.HasValue)
>> {
>> requestedHashCode = IsTransient() ? base.GetHashCode() : Id.GetHashCode();
>>  }
>> return requestedHashCode.Value;
>> }
>> Or equivalent if you are working with Natural-Id.
>>
>> P.S. take care with string concatenation in hashcode (different
>> concatenated strings may return same hash).
>>
>> 2009/2/21 Ayende Rahien <[email protected]>
>>
>> You are doing something wrong. Equals & GetHashCode should not change,
>>> and should be based on the ID of the object.
>>>
>>>
>>> On Sat, Feb 21, 2009 at 1:44 PM, Germán Schuager <[email protected]>wrote:
>>>
>>>> Hi, I'm seeing some odd behavior and I can't figure out where the
>>>> problem is...
>>>>
>>>>
>>>> I have the following classes:
>>>>
>>>>     public class Model
>>>>     {
>>>>         public virtual int ID { get; private set; }
>>>>
>>>>         public virtual string Name { get; set; }
>>>>
>>>>         ...
>>>>     }
>>>>
>>>>     public class Scheme
>>>>     {
>>>>         public virtual int ID { get; private set; }
>>>>
>>>>         public virtual string Name { get; set; }
>>>>
>>>>         private IDictionary<Model, decimal> rates = new
>>>> Dictionary<Model, decimal>();
>>>>
>>>>         public virtual IDictionary<Model, decimal> Rates
>>>>         {
>>>>             get
>>>>             {
>>>>                 return rates;
>>>>             }
>>>>         }
>>>>
>>>>         ...
>>>>     }
>>>>
>>>> I'd like to fetch an scheme, the rate collection and the models in a
>>>> single select, so I have the following code:
>>>>
>>>>     scheme = session.CreateQuery("from Scheme e left join fetch e.Rates
>>>> r left join fetch index(r) where e.Name = 'something'")
>>>>             .UniqueResult<Scheme>();
>>>>
>>>>     Assert.That(scheme.Rates.Count, Is.EqualTo(2));
>>>>
>>>>     var firstKey = scheme.Rates.Keys.First();
>>>>     Assert.That(scheme.Rates.ContainsKey(firstKey)); <--- FAILS!!!
>>>>
>>>> The problem is that the 2nd Assert fails with a KeyNotFoundException.
>>>>
>>>> Doing some research/debugging, it seems that NH is adding the entry to
>>>> the rates dictionary BEFORE assigning its properties, then when the
>>>> properties are assigned, the hash code of "model" (key of the dictionary
>>>> entry) change and the Dictionary<,> implementation does not found it
>>>> anymore.
>>>>
>>>> At first, I thought that I had wrong implementations of
>>>> Equals/GetHashCode, but the strange thing is that if I don't fetch the 
>>>> rates
>>>> dictionary keys in the query, it works ok (although they are lazy-loaded):
>>>>
>>>> from Scheme e left join fetch e.Rates r where e.Name = 'something'
>>>>
>>>> My implementation of Equals and GetHashCode in each class is like this:
>>>>
>>>>     public override bool Equals(object obj)
>>>>     {
>>>>         var other = obj as Model;
>>>>
>>>>         if (other == null)
>>>>             return false;
>>>>
>>>>         bool otherIsTransient = other.ID == 0;
>>>>         bool thisIsTransient = ID == 0;
>>>>         if (otherIsTransient && thisIsTransient)
>>>>             return ReferenceEquals(other, this);
>>>>
>>>>         return other.ID.Equals(ID);
>>>>     }
>>>>
>>>>     public override int GetHashCode()
>>>>     {
>>>>         return (GetType().FullName + "|" + (Name ?? "*")).GetHashCode();
>>>>     }
>>>>
>>>> Am I doing something wrong here or there is a problem somewhere else?
>>>> (I've put together a test solution in case that someone would like to
>>>> take a look)
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>
>>
>> --
>> 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