Сравнение значений равенства на новых объектах - PullRequest
1 голос
/ 09 апреля 2009

Я переопределил Equals и GetHashCode в абстрактном базовом классе, чтобы реализовать равенство значений на основе свойства ключа объекта. Моя основная цель - использовать метод Contains в коллекциях вместо Find или FirstOrDefault, чтобы проверить, был ли экземпляр уже добавлен в коллекцию.

public abstract class Entity
{
    public abstract Guid Id { get; }

    public override bool Equals(object obj)
    {
        if (obj == null)
        {
            return false;
        }

        if (obj.GetType() != GetType())
        {
            return false;
        }

        var entity = (Entity)obj;
        return (entity.Id == Id);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

}

Проблема этого подхода заключается в том, что все мои объекты равны до того, как они были сохранены и получили Id (сгенерированный NHibernate). Я делаю это неправильно? Я мог бы сгенерировать Id в конструкторе, но я хотел бы реализовать тот же шаблон для других проектов, которые используют int ids, так что это, очевидно, не будет работать.

Мне кажется, что любой объект, который переопределяет Equals, будет равен любому другому экземпляру того же объекта сразу после того, как объекты были созданы.

Отредактировано, чтобы добавить: Вот сценарий, который меня интересует: В методе Add для моих коллекций я проверяю, чтобы убедиться, что коллекция еще не содержит объект, который нужно добавить. Если все новые объекты равны, то я никогда не смогу добавить два новых объекта в коллекцию.

Ответы [ 4 ]

2 голосов
/ 09 апреля 2009

NHibernate гарантирует, что объект, ссылающийся на идентичность сущностей, связанных с одним и тем же контекстом, идентичен базе данных. Поэтому нет необходимости переопределять Equals () и GetHashCode (), потому что это та же самая идентичность, которую вы хотите реализовать.

См. 10.3. Considering object identity справочной документации NHibernate .

Кроме того, ассоциирование нового объекта с использованием ключей, сгенерированных базой данных, с контекстом должно постоянно сохранять объект в базе данных и устанавливать ключ объекта на сгенерированный ключ.

1 голос
/ 09 апреля 2009

Вы должны получить свой идентификатор или хотя бы какой-нибудь идентификатор в конструкторе.

Если идентификатор не установлен (или является значением по умолчанию); очевидно, метод Equals вернет true для любого объекта того же типа (который также не установил идентификатор).

0 голосов
/ 10 апреля 2009

Есть одна важная деталь, которая влияет на ваше решение:

... Я хотел бы реализовать то же самое шаблон для других проектов, которые используют int ids ...

Как правило, идентификаторы генерируются в базе данных для обеспечения уникальности . Теперь, когда у вас есть GUID, вам не нужно полагаться на базу данных для генерации значения - GUID гарантированно будут уникальными. Не следуйте шаблону по неправильным причинам:)

Итак, создайте значения GUID в конструкторе - просто убедитесь, что у вас есть установщик, чтобы NHibernate мог перезаписывать значение при получении объекта из базы данных.

Кроме того, вы можете рассмотреть возможность использования COMB GUID , если ваш администратор БД имеет отношение к GUID и фрагментации базы данных.

0 голосов
/ 09 апреля 2009

Может ли помочь, если вы вернете "не равно", если идентификатор не инициализирован?

public override bool Equals(object obj)
{
    if (obj == null)
    {
        return false;
    }

    if (obj.GetType() != GetType())
    {
        return false;
    }

    var entity = (Entity)obj;
    if ((Id == Guid.Empty) || (entity.Id == Guid.Empty))
    {
      return false;
    }
    return (entity.Id == Id);
}
...