NHibernate составной ключ против составного уникального ограничения

#c# #.net #nhibernate

#c# #.net #nhibernate

Вопрос:

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

Представьте настройку следующим образом:

 class Book
{
   public virtual int Id { get; protected set; }
   public virtual string Author { get; set; }
   public virtual IList<BookEdition> Editions { get; set; } //HasMany (one to many)
}

class BookEdition
{
   public virtual string Title { get; set; }
   public virtual string Language { get; set; }
   public virtual int Edition { get; set; }
}
  

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

Какой подход считается лучшим в NHibernate? Использовать язык / издание в качестве составного идентификатора или ввести переменную Id для BookEdition и вместо этого иметь составное уникальное ограничение?

Ответ №1:

Заменяющий ключ (дополнительная переменная Id) лучше в целом, а не только в NHibernate. Проблема с естественными ключами (здесь: Язык и редакция) заключается в том, что они имеют «деловое» значение. Потребности бизнеса развиваются со временем, и вам, безусловно, придется менять свои естественные ключи в будущем, что может быть очень болезненным. Кроме того, ваши SQL-соединения и условия where будут более сложными.

Это может быть FNH-сопоставление BookEdition с составным уникальным ограничением:

     Id(x => x.Id);
    Map(x => x.Title);
    Map(x => x.Language).UniqueKey("MyCompositeUniqueConstraint");
    Map(x => x.Edition).UniqueKey("MyCompositeUniqueConstraint");
  

Кстати. рекомендуется не показывать значения ключа surrorgate клиентам. Они склонны придавать им какое-то деловое значение, а затем также хотят их изменить :).

Комментарии:

1. Это было сопоставление, о котором я тоже думал. Хорошая ли идея переопределить Equals / GetHashCode также для использования естественного ключа? В моем базовом классе у меня есть оператор Equals, который работает со свойством Id, но это неточно для данного случая. Я думаю, также невозможно иметь составной естественный ключ, используя «NaturalID()». Я также не очень понимаю разницу между естественным идентификатором и уникальным ограничением в терминах гибернации..

2. Уникальное ограничение IMO (или ключ) не играет никакой роли во внутренностях NH. Это всего лишь руководство по созданию db. schema (создание ограничения для таблицы). С другой стороны, первичный ключ (составной, естественный, окружающий — не имеет значения) является фундаментальной концепцией для ИЛИ отображения. В нем говорится, как однозначно найти объект в таблице базы данных.

3. Хм, кажется, что всегда полезно переопределять Equals и, следовательно, GetHashCode, особенно когда задействованы отложенная загрузка и прокси ( devlicio.us/blogs/billy_mccafferty/archive/2007/04/25 /… ). Очень интересно, спасибо за ваш вопрос, похоже, я пока ничего не знаю о NH :).