NHibernate отношения многие-к-одному, удаление только родитель - PullRequest
1 голос
/ 29 апреля 2009

У меня есть отношение многие-к-одному между объектами Product и Supplier. Мне нужно иметь возможность удалить Supplier без удаления принадлежащих ему Product.

Вот упрощенная версия классов:

public class Supplier {
    public virtual IList<Product> Products { get; protected set; }
}

public class Product {
    // Product belongs to a Category but Supplier is optional
    public virtual Supplier Supplier { get; set; }
    public virtual Category Category { get; set; }
}

Я использую FluentNHibernate, но вот сопоставления, которые он производит:

<bag name="Products" cascade="save-update" inverse="true">
      <key column="SupplierID" />
      <one-to-many class="Me.Product, Me, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>

<many-to-one name="Supplier" column="SupplierID" />

Это создает внешний ключ в таблице «Продукты», поэтому, когда я пытаюсь выполнить прямое удаление поставщика, я получаю ошибку ограничения внешнего ключа. Я попытался изменить каскад на «все» в надежде, что он может только удалить связь, но он удалил все Продукты и их другие связанные объекты.

Единственный способ решить эту проблему прямо сейчас - это выполнить итерацию коллекции Products поставщика и установить для свойства Supplier значение null. Есть ли способ, которым я могу добиться этого поведения с помощью сопоставления?

Ответы [ 2 ]

2 голосов
/ 29 апреля 2009

Свойства отображения вступают в силу только тогда, когда сущность действительно загружена, и когда вы не запрашиваете через HQL. Например, если вы укажете Cascade=ALL, если вы удалите поставщика с запросом "delete from Supplier where id=:id", вы, вероятно, получите тот же сбой ограничения FK, поскольку hql не запускает (программные) каскады.

Кажется, что Продукты - это сторона отношений, и это хорошо. Я думаю, у вас есть два варианта:

  • Запишите какой-либо метод для Поставщика, чтобы выполнить итерацию по всем Продуктам, и установите для поставщика Продукта значение NULL, и используйте этот метод перед удалением любых Поставщиков
  • Перед выдачей удаления поставщика убедитесь, что ваш DAO устанавливает поставщика продукта на ноль

Пример:

public int Delete(Supplier s) {
    return Session.CreateQuery("udpate Product set Supplier = null where Supplier = :supplier")
        .SetParameter("supplier", s)
        .ExecuteUpdate();
}
0 голосов
/ 29 апреля 2009

НЕ ДЕЛАЙТЕ ЭТОГО.

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

Единственное, что вы можете сделать, вы уже обнаружили: для каждого Продукта, у которого есть этот Поставщик, вы можете установить нулевого Поставщика Продукта. Это не будет нарушать ваше состояние, но это то же самое, что сказать «мы не знаем, кто является поставщиком данного продукта», и может привести к ошибкам кода.

Почему вы хотите это сделать?

...