поведение nhibernate gethashcode - PullRequest
0 голосов
/ 07 июня 2011

Последние три дня я боролся с забавным, по крайней мере для меня, поведением.Основная концепция заключается в следующем: объект создается в памяти, этот объект имеет список дочерних элементов.Этот объект сохраняется в БД, дети также сохраняются, каскадный режим.Это работает нормально, но если после сохранения я пытаюсь удалить одного потомка, удалив из списка, это не сработает, список не удалит потомка.Я обнаружил, что список типа HashedSet каким-то образом кэширует хэш-код объекта, когда он впервые добавляется в список, перед сохранением, после сохранения тот же объект не имеет того же хеш-кода.Но список все еще предполагает старый хэш-код.Я переопределил GetHashCode и Equals, после долгих поисков и поисков, я обнаружил сообщение в блоге , в котором объясняется использование nhibernate для методов GetHashCode и Equals.

Это моя реализация

    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));
    }

Я использовал переменную orgHashCode, которая возвращает хеш-код перед первым сгенерированным хеш-кодом, если я использую этот метод, кажется, что он работает, но я думаю, чтоэто не лучшее решение, хеш-код должен генерироваться для текущего объекта, а не для «его первой версии».

Я не знаю, достаточно ли понятно мое объяснение.Любые советы будут высоко оценены.Спасибо

Ответы [ 2 ]

0 голосов
/ 08 июня 2011

Только что нашел ответ на мою проблему. Проблема в словаре, в котором содержится дочерний список. Здесь хранится ключ с использованием HashCode объекта, если GetHashCode объекта переопределен, как в моем случае, он должен вернутьзначение, которое должно быть неизменным в течение срока службы объекта, чего в моем случае не происходит.Поэтому, когда элемент добавляется в список, GetHashCode возвращает одно значение, но после того, как я сохраню объект в базе данных, GetHashCode изменится, но словарь по-прежнему содержит исходный HashCode для объекта, если я выполню удаление или содержит, потому что значенияРазница в словаре не находит объект, хотя он существует в списке Этот вопрос может лучше объяснить мою проблему

0 голосов
/ 08 июня 2011

Есть ли у вас каскадный режим для all-delete-orphan ?Этот каскадный режим позволяет удалять объекты при их удалении из коллекции.

...