开发者

nhibernate gethashcode behaviour

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


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


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜