Обновление NHibernate с использованием составного ключа - PullRequest
1 голос
/ 11 мая 2010

У меня есть таблица определений, приведенная ниже:

Лицензия

ClientId
Type
Total
Used

ClientId и Type вместе однозначно определяют строку. У меня есть файл сопоставления, как указано ниже:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
  <class name="Acumen.AAM.Domain.Model.License, Acumen.AAM.Domain" lazy="false" table="License">
<id name="ClientId" access="field" column="ClientID" />
<property name="Total" access="field" column="Total"/>
<property name="Used" access="field" column="Used"/>
<property name="Type" access="field" column="Type"/>
  </class>
</hibernate-mapping>

Если клиент использовал лицензию для создания пользователя, мне нужно обновить столбец Используется в таблице. Поскольку я устанавливаю столбец ClientId в качестве столбца идентификатора для этой таблицы в сопоставлении xml, я получаю TooManyRowsActedException.

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

Что-то вроде: Обновление лицензии SET Used = Used-1 WHERE ClientId = 'xxx' AND Type = 1

Пожалуйста, помогите.

Спасибо, Махеш

Ответы [ 3 ]

3 голосов
/ 11 мая 2010

Вы должны использовать составной идентификатор

http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-compositeid

2 голосов
/ 11 мая 2010

Если ваш первичный ключ является составным, ваше отображение должно отражать это, и ваш класс должен переопределить Equals и GetHashCode.

Также, если ClientId является первичным ключом вашей Client сущности, вы должны отобразить его как many-to-many, а не просто Id.

Кроме того, почему вы указываете lazy="false"? Вы знаете о последствиях?

Кроме того, зачем сопоставлять все с access="field"? У свойств есть какая-то особая логика?

Это пересмотренное отображение, учитывающее все, что я только что написал. Не стесняйтесь игнорировать те части, которые не применяются: -)

<class name="Acumen.AAM.Domain.Model.License, Acumen.AAM.Domain" table="License">
  <composite-id>
    <key-many-to-one name="Client" column="ClientID" />
    <key-property name="Type" />
  </composite-id>
  <property name="Total" />
  <property name="Used" />
</class>
1 голос
/ 11 мая 2010

Как и другим упомянутым выше товарищам, вы должны использовать составной идентификатор, что не является лучшей, но приемлемой практикой.

С другой стороны, вы можете просто написать перехватчик обновлений и убедиться, что в нем указан тип = 1.

Вот несколько ссылок на эту тему, чтобы помочь вам понять это.

  1. Элегантный код: внедрение перехватчиков NHibernate
  2. NHibernate Документация: перехватчики
  3. Пример реализации II-рецептора NHibernate
  4. Enterprise .NET Community: NHibernate Часть 2 (Прокрутите вниз до: Перехватчики и постоянный жизненный цикл )
  5. Идентификатор вставленного объекта в NHibernate Interceptor Id (вопрос SO)

Основным преимуществом использования перехватчиков над составным ключом является то, что он не нарушает вашу DBRM и обеспечивает определенно более гибкое решение, не "загрязняя" файл сопоставления, который будет более точно представлять вашу модель.

...