Подтвердить что ты не робот

Как удалить дочерний объект в NHibernate?

У меня есть родительский объект, который имеет отношение один к многим с 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: просто для пояснения - я НЕ пытаюсь удалить родительский объект, а только дочерние объекты. У меня есть отношения, установленные как один для многих на родителя. Нужно ли мне также создавать отношения "много-к-одному" при сопоставлении дочерних объектов?

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Сообщение имеет много MessageSentTo:

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

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

Ответ 3

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

Ответ 4

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

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

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

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

Ответ 5

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

Ответ 6

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