Как удалить отношения «многие ко многим»? - PullRequest
5 голосов
/ 15 марта 2012

У меня есть отношения многие ко многим:

Товар имеет много категорий, а категория имеет много товаров.

Скажи, что у меня

Shopping Category  
Food Category

Product A - Shopping Category, Food Category  
Product B - Shopping Category

Теперь я удаляю Shopping Category. Я хочу, чтобы ссылка Product A была удалена из Shopping Category, и я хочу, чтобы Product B был удален полностью.

Я бы закончил с:

Product A - Food Category.

Как мне это сделать в nhibernate (я использую свободный nhibernate).

Я пытался использовать Cascade DeleteOrphan и AllDeleteOrphan, но когда я это делаю и удаляю покупки, оба продукта A и B. удаляются.

public class CategoryMapping : ClassMap<Category>
{
    public CategoryMapping()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();

        Map(x => x.Name).Not.Nullable().NvarcharWithMaxSize();
        HasManyToMany(x => x.Products).Cascade.DeleteOrphan();
    }
}


public class ProductMapping : ClassMap<Product>
{
    public ProductMapping()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.Name).Not.Nullable().NvarcharWithMaxSize();
        HasManyToMany(x => x.Categories);
    }
}

  unitOfWork.BeginTransaction();
  Category category =session.Load<Category>(id);
  session.Delete(category);
  unitOfWork.Commit();

Ответы [ 2 ]

2 голосов
/ 26 марта 2012

Я не думаю, что это можно сделать путем сопоставления с существующей структурой данных. Я думаю, вам нужно написать какой-нибудь ручной код (*) или изменить структуру данных.

(*) Не уверен, что он работает на 100% ...

unitOfWork.BeginTransaction();
Category category =session.Load<Category>(id);
var productsDel = category.Products.Where(p => p.Categories.Count == 1);
productsDel.ForEach(p => session.Delete(p));
session.Delete(category);
unitOfWork.Commit();

Другое:

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

0 голосов
/ 15 марта 2012

Если вы просто хотите удалить связь между двумя, используйте Cascade.SaveUpdate()

Затем просто удалите объект из коллекции и зафиксируйте транзакцию, если вы используете транзакции, если нет, вам нужно будет выполнить Session.Flush

...