Удалить Родителя и Ребенка без каскада - PullRequest
1 голос
/ 17 августа 2011

Мой код накапливает объект удаляет и обновляет от пользователя, а затем пытается применить те в один выстрел.В случае, если у меня возникли проблемы, это бизнес-требование, что родитель удаляется только в том случае, если не осталось дочерних элементов, но дочерние элементы должны быть удалены вручную.

Я могу воспроизвести проблему с помощью следующегокод:

Отображение:

<class name="SomeClass" >
  <id name="ID">
    <generator class="native" />
  </id>
  <property name="Name" />
  <many-to-one name="Parent" not-null="true" />
</class>

<class name="SomeParent" >
  <id name="ID">
    <generator class="native" />
  </id>
  <property name="Name" />
  <set name="Children" batch-size="100" inverse="true">
    <key column="Parent" not-null="true" />
    <one-to-many class="SomeClass" />
  </set>
</class>

Объекты:

public class SomeClass
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual SomeParent Parent { get; set; }
}

public class SomeParent
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual ISet<SomeClass> Children { get; set; }
}

Программа:

using (var sessionFactory = cfg.BuildSessionFactory())
using (var session = sessionFactory.OpenSession())
{
    var p = new SomeParent();
    var obj = new SomeClass() { Parent = p };
    session.Save(p);
    session.Save(obj);
    session.Flush();
}

using (var sessionFactory = cfg.BuildSessionFactory())
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
    foreach (var p in session.CreateCriteria<SomeParent>().List<SomeParent>())
    {
        session.Delete(p);
    }

    foreach (var p in session.CreateCriteria<SomeClass>().List<SomeClass>())
    {
        session.Delete(p);
    }

    session.Flush();
    tx.Commit();
}

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

Этот пример также работает, если я добавлю cascade="delete" к отображению one-to-many.Это нарушает бизнес-требование о том, что родители не могут быть удалены, пока у них есть дети.

Я бы ожидал, что NHibernate выполнит этот заказ для меня.Тем более, что вся необходимая информация уже доступна в картографии.Я просто делаю что-то не так или мне нужно "вручную" отсортировать удаления правильно, чтобы NHibernate получал их?

Я использую NHibernate 3.2.0GA (сборка 3.2.0.4000 из nuget).

1 Ответ

1 голос
/ 17 августа 2011

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

Мое предложение состоит в том, чтобы отслеживать удаления в коллекции и не запускать удаления NHibernate до тех пор, пока данные не будут проверены. То есть создайте методы MarkForDeletion для родительских и дочерних объектов. Когда пользователь нажимает кнопку «Удалить», эти методы добавляют объект в коллекцию.

Когда пользователь готов совершить транзакцию, циклически просматривайте дочерние объекты, помеченные для удаления, удаляйте их из дочерней коллекции родителя и устанавливайте для ссылки на родителя значение null. Затем переберите родительские объекты, помеченные для удаления, и проверьте, что их дочерняя коллекция пуста.

Если данные действительны, вы можете затем удалить родительские объекты и позволить настройке каскада (all или all-delete-orphan) позаботиться о дочерних записях.

...