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