NHibernate отображение списка компонентов с ограничением уникального ключа - PullRequest
2 голосов
/ 11 марта 2011

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

Ниже приведен «обрезанный» образец классов:

public class MyObject
{
    public virtual int Id { get; set; }
    public virtual IList<Alias> Aliases { get; set; }
}

public class Alias
{
    public Alias(string type, string value)
    {
        Type = type;
        Value = value;
    }

    public virtual string Type { get; protected set; }
    public virtual string Value { get; protected set; }
}

и соответствующее отображение NHibernate из MyObject (типы были обрезаны для краткости):

  <list cascade="all-delete-orphan" name="Aliases" table="MyObject_Aliases" mutable="true">
      <key>
        <column name="MyObject_id" />
      </key>
      <index>
        <column name="`Index`" />
      </index>
      <composite-element class="Alias">
        <property name="Type" type="System.String">
          <column name="Type" unique-key="UK_Alias" />
        </property>
        <property name="Value" type="System.String">
          <column name="Value" unique-key="UK_Alias" />
        </property>
      </composite-element>
    </list>

Цель состоит в том, чтобы два объекта MyObject не содержали один и тот же псевдоним.

Это прекрасно работает при добавлении нового псевдонима в MyObject.Однако если вы удалите псевдоним из списка, в котором после псевдонима есть псевдонимы, NHibernate попытается изменить порядок списка, что приведет к нарушению ключа.

Пример SQL, который генерирует NHibernate:

-- statement #1, saving MyObject.Aliases
INSERT INTO MyObject_Aliases
           (MyObject_id,
            "Index",
            Type,
            Value)
VALUES     (101 /* @p0 */,
            0 /* @p1 */,
            'A' /* @p2 */,
            'ALIAS1' /* @p3 */)

INSERT INTO MyObject_Aliases
           (MyObject_id,
            "Index",
            Type,
            Value)
VALUES     (101 /* @p0 */,
            1 /* @p1 */,
            'A' /* @p2 */,
            'ALIAS2' /* @p3 */)

-- statement #2, updating MyObject.Aliases after removing the first list item
UPDATE MyObject_Aliases
SET    Type = 'A' /* @p0 */,
       Value = 'ALIAS2' /* @p1 */
WHERE  MyObject_id = 101 /* @p2 */
       AND "Index" = 0 /* @p3 */

Оператор # 2 в этом примере выдает:

NHibernate.Exceptions.GenericADOException : could not update collection rows: [MyObject.Aliases#101][SQL: UPDATE MyObject_Aliases SET Type = ?, Value = ? WHERE MyObject_id = ? AND "Index" = ?]
  ----> System.Data.SQLite.SQLiteException : Abort due to constraint violation
columns Type, Value are not unique

Само исключение имеет смысл в зависимости от того, что происходит на самом деле, но как мне заставить его работать так, как ожидалось?

1 Ответ

1 голос
/ 11 марта 2011

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

...