2010-01-20 3 views
7

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

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

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

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

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 , Причина, по которой не использовать первичные ключи базы данных в качестве значений сравнения, заключается в том, что это изменит хэш-код объекта, если первичный ключ не создается на стороне клиента (для ex incremental), и вы используете какую-то коллекцию хэш-таблиц (например, ISet) для хранения ваших объектов.

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

+0

Почему вы (в частности) хотите/должны использовать равные? – apollodude217

ответ

13

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

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

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

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

Вы можете решить, присвоить значение PK в коде, таким образом, объект имеет всегда идентификатор и может быть использован для сравнения. См. Don't let hibernate steal your identity.

3 Природный ключ

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

4 Объект значения

Используя значения объекта для равенства возможно. Но есть другие недостатки, о которых вы говорили. Это может быть проблематично, если значения меняются, а объект находится в коллекции .Например, если у вас есть Set с двумя объектами, которые были разными поначалу, но затем вы меняете значения, пока они являются ссылкой в ​​наборе, чтобы они стали равными. Затем вы нарушаете договор Set. См. Hibernate equals and hashcode.

5 Смешанные: значение + AutoGenerate первичных/суррогатных ключей

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

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

+0

Я не вижу opt 1 как проблему, если вы не хешируете свои объекты до их сохранения (например, не используйте коллекции ISet). – Marius

+0

Ницца (+1) Поздравления –

Смежные вопросы