0

I'm have been struggling the last 3 days with a funny, at least for me, behaviour. The basic concept is the following: An object is created in memory, this object has a list of children. This object is saved into the DB, the children are also saved, cascade mode. This works fine, but if after I the save then I try to delete one child, removing from the list, this doesn't work, the list doesn't remove the child. What I found is that the list, HashedSet type, somehow caches the hashcode of the object when it is first inserted to the list, before the save, after the save the same object doesn't have the same hashcode. But the list still assumes the old hashcode. I have overriden the GetHashCode and Equals, after a lot of googling and reading, I found a blog post that explains the use that nhibernate does of the GetHashCode and Equals methods.

This is my implementation

    public override int GetHashCode()
    {
        if (orgHashCode.HasValue)
            return orgHashCode.Value;

        var hashCode = 17;
        var signatureProperties = GetSignatureProperties();

        if (!IsTransient())
            hashCode = (hashCode*HASH_MULTIPLIER) ^ GetIdValue().GetHashCode();
        else
        {
            foreach (var property in signatureProperties)
            {
                object value = property.GetValue(this, null);

                if (value != null)
                    hashCode = (hashCode*HASH_MULTIPLIER) ^ value.GetHashCode();
            }
        }

        if (!orgHashCode.HasValue)
            orgHashCode = hashCode;


        // If no properties were flagged as being part of the signature of the object,
        // then simply return the hashcode of the base object as the hashcode.
        return signatureProperties.Any() ? hashCode : base.GetHashCode();
   }

    public override bool Equals(object obj)
    {
        var compareTo = obj as DbCommonBase;

        if (ReferenceEquals(this, compareTo))
            return true;

        return compareTo != null &&
                GetType().Equals(compareTo.GetUnproxiedType()) &&
                (HasSameNonDefaultIdAs(compareTo) || ((IsTransient()) || compareTo.IsTransient()) &&
                HasSameObjectSignatureAs(compareTo));
    }

I have used a variable called orgHashCode that return the hashcode before the first hashcode generated, if I use this method it seems that it works, but I think that this is not the best solution, the hashcode should be generate for the current object and not for "the first version" of it.

I don't know if my explanation is clear enough. Any hints would be much appreciated. Thanks

Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
Ruben Monteiro
  • 315
  • 3
  • 15

2 Answers2

0

Do you have cascade mode to all-delete-orphan? This cascade mode allows deletion of objects when they are removed from collection.

Sly
  • 15,046
  • 12
  • 60
  • 89
  • Hi, thanks for the reply, I tried with both Cascade.All and Cascade.AllDeleteOrphan, I'm using fluentNhibernate. The problem still happens. The problem is not on nhibernate it self. This is what happens to me, if I create an object and to this object add childs to its child list and then I persist this new object in the database, this works fine. But if after this is in the same nhibernate session I try to delete on of the childs it doesn't. – Ruben Monteiro Jun 08 '11 at 11:03
  • Because the list that holds the child keeps the hashcode of the child before save, but the child after save has a different hashcode, so the remove method of the list doesn't work alhough if I do an equals it returns true for the child object in question – Ruben Monteiro Jun 08 '11 at 11:03
0

Just found the answer to my problem, The problem in the dictionary that hold the child list, this store the key using the HashCode of the object, if the GetHashCode of the object is overriden, like in my case, it should return a value that should be immutable during the life time of the object, which in my case it isn't happening. So when the item is added to the list the GetHashCode returns one value, but after I save the object to the database the GetHashCode changes but the dictionary still holds the original HashCode for the object, if I do a remove or contains because the values are differents the dictionary doesn't find the object although it exists in the list This question can explain better my problem

Community
  • 1
  • 1
Ruben Monteiro
  • 315
  • 3
  • 15
  • I'm not sure, I think you have already seen it, but this link may help you: http://sharp-architecture.googlecode.com/svn/trunk/src/SharpArch/SharpArch.Core/DomainModel/BaseObject.cs – Guillermo Gutiérrez Jun 18 '13 at 23:47