nhibernate: каковы лучшие практики для реализации равенства?

Я думаю, что Объекты должны реализовать равенство по сравнению первичного ключа как значение по умолчанию, но nhibernate документация рекомендует использовать бизнес-идентификационные данные:

Самый очевидный путь состоит в том, чтобы реализовать, Равняется ()/GetHashCode () путем сравнения значения идентификатора обоих объектов. Если значение является тем же, оба должны быть той же строкой базы данных, они поэтому равны (если оба будут добавлены к ISet, то у нас только будет один элемент в ISet). К сожалению, мы не можем использовать тот подход. NHibernate только присвоит значения идентификатора объектам, которые постоянны, недавно созданный экземпляр не будет иметь никакого значения идентификатора! Мы рекомендуем реализовать, Равняется () и GetHashCode () использование Бизнес-ключевого равенства.

Бизнес-ключевое равенство означает, что Равняние () метод сравнивает только свойства, которые формируют бизнес-ключ, ключ, который определил бы наш экземпляр в реальном мире (ключ наиболее подходящего кандидата)

И пример (также из документа):

public override bool Equals(object other)
{
    if (this == other) return true;

    Cat cat = other as Cat;
    if (cat == null) return false; // null or not a cat

    if (Name != cat.Name) return false;
    if (!Birthday.Equals(cat.Birthday)) return false;

    return true;
}

Это получило мою голову, вращающуюся, потому что понятие бизнес-идентификационных данных (согласно примеру) совпадает со сравнением синтаксисом, который является в основном типом семантики, которую я связываю с ValueObjects. Причина того, что не использовались первичные ключи базы данных в качестве сравнительных значений состоит в том, потому что это изменит хэш-код объекта, если первичный ключ не будет сгенерирован на стороне клиента (для исключая возрастающим), и Вы используете своего рода набор хеш-таблицы (такой как ISet) для хранения Ваших объектов.

Как я могу создать хорошую реализацию равенства, которая не нарушает общие правила для равенства/хэш-кода (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) и соответствует правилам nhibernate также?

7
задан Marius 20 January 2010 в 09:26
поделиться

1 ответ

Это известная проблема с ORM. Здесь я описываю решения, о которых я знаю и даю несколько указателей.

1 Суррогатный / первичный ключ: автоматически генерируется

, как вы упоминали, если объект не был сохранен, это не работает.

2 Суррогатный / первичный ключ: присвоенное значение

Вы можете решить назначить значение PK в коде, таким образом, этот объект всегда имеет идентификатор и может использоваться для сравнения. См. Не позволяйте гибернации украсть вашу личность .

3 Натуральный ключ

Если объект имеет еще один натуральный ключ, кроме первичного ключа, вы можете использовать этот. Это было бы в случае для клиентского объекта, который имеет числовой первичный ключ и Номер клиента строки. Номер клиента идентифицирует клиента в реальном мире и является естественным ключом, который не изменится.

Возможен 4 значения объекта

, используя значения объектов для равенства. Но есть ли другие недостатки, вы упомянули. Это может быть проблематично, если значения изменения, и объект находится в коллекции . Например, если у вас есть SET с двумя объектами, которые были сначала разные, но затем вы изменяете значения, когда они ссылаются на набор, чтобы они стали равными. Затем вы нарушаете договор набора . См. Hibernate равна и Hashcode .

5 Смешанные: значение + Автогената Первичные / суррогатные клавиши

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

У всех есть некоторые плюсы и минусы. ИМХО, лучшее - это 3, если это возможно с вашей моделью домена. В противном случае я использовал 5, и он работал, хотя при использовании коллекций все еще есть какая-то ловушка. Я никогда не использовал 2, но это звучит также разумное решение, если вы найдете способ генерировать PK в коде. Может быть, другие у людей есть указатели для этого.

13
ответ дан 6 December 2019 в 19:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: