Отношения NHibernate «многие к одному», удаляющие только родителя

StackOverflow https://stackoverflow.com/questions/801730

Вопрос

У меня есть связь «многие к одному» между объектами 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 поставщика и установить для свойства Поставщика значение null.Есть ли способ добиться такого поведения с помощью сопоставления?

Это было полезно?

Решение

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

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

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

Пример:

public int Delete(Supplier s) {
    return Session.CreateQuery("udpate Product set Supplier = null where Supplier = :supplier")
        .SetParameter("supplier", s)
        .ExecuteUpdate();
}

Другие советы

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

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

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

почему ты хочешь сделать это?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top