Как удалить дочерний объект в NHibernate? - PullRequest
78 голосов
/ 19 ноября 2008

У меня есть родительский объект, который имеет отношение один ко многим с IList дочерних объектов. Каков наилучший способ удаления дочерних объектов? Я не удаляю родителя. Мой родительский объект содержит IList дочерних объектов. Вот отображение для отношения один ко многим:

<bag name="Tiers" cascade="all">
  <key column="mismatch_id_no" />
  <one-to-many class="TGR_BL.PromoTier,TGR_BL"/>
</bag>

Если я пытаюсь удалить все объекты из коллекции с помощью clear (), а затем вызвать SaveOrUpdate (), я получаю следующее исключение:

System.Data.SqlClient.SqlException: Cannot insert the value NULL into column

Если я пытаюсь удалить дочерние объекты по отдельности, а затем удалить их из родительского объекта, я получаю исключение:

deleted object would be re-saved by cascade

Я впервые имею дело с удалением дочерних объектов в NHibernate. Что я делаю не так?

edit: Просто чтобы уточнить - я НЕ пытаюсь удалить родительский объект, только дочерние объекты. У меня есть отношения, настроенные как один ко многим на родителя. Нужно ли также создавать отношение многие-к-одному в сопоставлении дочерних объектов?

Ответы [ 6 ]

135 голосов
/ 19 ноября 2008

Вы получаете первую ошибку, потому что, когда вы удаляете элементы из коллекции, стандартным режимом работы NHibernate является просто разрыв связи. В базе данных NHibernate пытается установить для столбца внешнего ключа в дочерней строке значение null. Так как вы не разрешаете пустые значения в этом столбце, SQL Server вызывает ошибку. Очистка коллекции не обязательно удалит дочерний объект, но один из способов сделать это - установить cascade = all-delete-orphan. Это сообщает NHibernate, что он должен удалить вновь потерянные строки вместо установки столбца внешнего ключа.

Вы получаете вторую ошибку, потому что при вызове SaveOrUpdate NHibernate сначала удаляет все дочерние объекты. Затем, поскольку ни одно из отношений не помечено как обратное, NHibernate также пытается установить для столбца внешнего ключа в вашей дочерней таблице значение null. Поскольку строки уже были удалены, вы получите вторую ошибку. Вам нужно установить inverse = true на одной стороне ваших отношений, чтобы это исправить. Обычно это делается на одной стороне (первичный ключ или родительский). Если вы этого не сделаете, NHibernate сделает соответствующие обновления для каждой стороны отношений. К сожалению, запуск двух обновлений не подходит.

Вы всегда должны отмечать одну сторону ваших отношений как обратную сторону. В зависимости от того, как вы кодируете, вам может понадобиться или не потребоваться каскадирование. Если вы хотите использовать одно удаление, как вы пытаетесь сделать с помощью Clear (), вам нужно определить свой каскад.

3 голосов
/ 23 июля 2010

Согласно ответу Чака, я решил свою проблему, добавив Inverse = true в отображение родительской стороны:

В сообщении много сообщенийSentTo:

[HasMany(typeof(MessageSentTo), Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)]
public IList<MessageSentTo> MessageSendTos
{
    get { return m_MessageSendTo; }
    set { m_MessageSendTo = value; }
}

Я использую Замок ActiveRecord. Спасибо, Чак.

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

В нашем примере у нас есть категории с множеством товаров, где товар не обнуляется.

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

product = pRepo.GetByID(newProduct.ProductID);
product.Category.Products.Remove(product);
pRepo.Delete(product);

Надеюсь, это все равно поможет

2 голосов
/ 19 ноября 2008

Попробуйте использовать merge () вместо saveOrUpdate (). Кроме того, убедитесь, что для вашего каскада установлено значение all-delete-orphan, и что ваши родительско-дочерние отношения являются обратимыми (inverse = true для родительского элемента, а затем поле в дочернем элементе, которое является идентификатором parent с not-null = true) .

0 голосов
/ 19 ноября 2008

Измените значение атрибута каскада со "all" на "all-delete-orphan".

0 голосов
/ 19 ноября 2008

set Not-Null = true в отображении столбца, вызывающего проблему. Хотя я не уверен в точном синтаксисе (извините).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...