Избегание идентификации объекта с помощью NHibernate

#c# #nhibernate

#c# #nhibernate

Вопрос:

Я пытаюсь изучить NHibernate, и я столкнулся с проблемой комбинированного проектирования базы данных / «изучения того, как работает NHibernate».

В моем случае я пытаюсь создать простую таблицу со строками и столбцами, где каждая строка имеет «описание», а затем список «значений столбцов» (сортировок), который содержит данные, а также информацию о сортировке. В коде это будет выглядеть примерно так:

 public class Row
{
    public virtual int ID { get; set; }
    public virtual string Description { get; set; }
    public virtual ICollection<Column> Columns { get; set; }
}

public class Column
{
    public virtual Row ParentRow { get; set; }
    public virtual int SortID { get; set; }
    public virtual string Value { get; set; }
}
 

Моей конечной целью было создать схему базы данных, которая была бы…

  • Две таблицы, «Строка» и «Столбец»
  • Строка содержит два столбца: идентификатор и описание.
  • Столбец состоит из трех столбцов: ParentID, SortID и Value.

Поскольку столбец может принадлежать только одной строке, и в идеале каждый столбец должен иметь уникальный идентификатор сортировки внутри каждого родительского идентификатора, первичным ключом таблицы столбцов могут быть ParentID и SortID вместо четвертого столбца «ID».

Однако NHibernate борется со мной на каждом шагу. Он настаивает на том, что у меня должен быть идентификатор для поля столбца. Полагаю, у меня есть несколько вопросов:

  1. Является ли моя «цель схемы» сама по себе такой серьезной ошибкой? Действительно ли было бы лучше, если бы каждый столбец имел свой собственный идентификатор? Если да, то почему?
  2. Независимо от того, является ли схема, которую я ищу, хорошим дизайном, может ли это быть выполнено в NHibernate? До сих пор я успешно сопоставил класс «Row», но я не могу сопоставить класс «Column» без того, чтобы NHibernate не жаловался, что я должен предоставить ему идентификатор. (для чего это стоит, я использую Fluent NHibernate). Как мне это обойти?

Ответ №1:

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

Чтобы узнать, как сопоставлять составные идентификаторы первичного ключа, прочитайте раздел composite-id из документации Nhibernate.

Все это говорит о том, что, исходя из опыта, я обнаружил, что несоставные идентификаторы первичного ключа являются вашим лучшим другом ORMs. Это значительно упрощает жизнь во многих случаях, таких как генерация идентификаторов на основе приложений, пакетирование и т. Д. В таблицах, похожих на вашу таблицу «столбец», я предпочитаю иметь синтетический идентификатор первичного ключа (суррогатный ключ). Но опять же, это зависит от ваших потребностей, YMMV.

Ответ №2:

в моделировании ООП существует два разных типа. Ссылочные типы и типы значений. Разница между ними заключается в том, что для ссылочных типов вам важно, какие они есть, которые идентифицируются некоторым идентификатором, а для типов значений вам важно, какие они есть.

Простым примером в мире .net является

DateTime d1 = новое DateTime(2012,12,21);

DateTime d2 = новое DateTime(2012,12,21);

Теперь нас действительно волнует, указывают ли эти два времени даты на разные экземпляры памяти (и они указывают на это)

Нет, но мы просто заботимся о том, что они собой представляют, следовательно, они равны.

Сначала вы должны решить, должна ли ваша сущность быть типом значения или ссылочным типом. Если это ссылочный тип, вы должны следовать приведенному выше определению и присвоить nhibernate некоторый идентификатор. Если вы не можете указать идентификатор, тогда это должен быть тип значения. В этом случае вам все равно, какой это, но что это такое. Для такого случая nhibernate предлагает вам компоненты. С компонентами, которые могут находиться в одной таблице или отдельно, нет необходимости определять идентификатор. Однако nhibernate не будет рассматривать их как сущность.