These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 
Author Message
 Post subject: Cascade="all-delete-orphan"
PostPosted: Mon Nov 16, 2009 10:05 am 
Newbie

Joined: Mon Nov 02, 2009 9:52 am
Posts: 19
I have read all-delete-orphan would delete every orphaned child of the deleted object.
I understood it as the following:
In a parent child context, I have 3 objects, Adam, Peter and Claire. Peter is the child of Adam and Claire is the child of Peter.
If I delete Claire, Peter and Adam are still persistent. If I would delete Peter, only Adam would be still persistent. Does this make sense? Ok, now to my question:

If I delete Claire in my project, NHibernate deletes every single object, that is associated with Claire. I would expect only Claire to be deleted...

My Class:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace NewNHibernate
{
    public class Person
    {
        public virtual int _id { get; set; }
        public virtual String _name { get; set; }
        public virtual Person _parent { get; set; }
        public virtual IList<Person> Children { get; set; }

        public Person()
        { }

        public Person(String name, Person parent)
        {
            _name = name;
            _parent = parent;

            Children = new List<Person>();

            if (null != parent)
            {
                parent.Children.Add(this);
            }
        }

        public virtual bool IsRoot()
        {
            return null == _parent ? true : false;
        }

        public virtual Person GetRoot()
        {
            Person root = _parent;

            while (root._parent != null)
            {
                root = root._parent;
            }

            return root;
        }

        public virtual Person AddChild(Person child)
        {
            child._parent = this;
            Person ancestor = this;

            while (ancestor._parent != null)
            {
                ancestor._parent = ancestor._parent._parent;
            }

            ancestor.Children.Add(child);

            return child;
        }
    }
}


My mapping:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="false">
<class name="NewNHibernate.Person, NewNHibernate">

    <id name="_id" column="id" type="int" unsaved-value="0">
      <generator class="identity" />
    </id>
    <property name="_name" column="name" type="string" not-null="true" unique="true" />

    <many-to-one name="_parent" column="parent" class="NewNHibernate.Person" cascade="all-delete-orphan"/>

    <bag name="Children" cascade="all-delete-orphan" inverse="true">
      <key column="parent" foreign-key="FK_Person_Children" />
      <one-to-many class="NewNHibernate.Person"/>
    </bag>
 
  </class> 
</hibernate-mapping>


My Program:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;

namespace NewNHibernate
{
    class Program
    {
        static void Main(string[] args)
        {
            Person Adam = new Person("Adam", null);
            Person Peter = new Person("Peter", Adam);
            Person Claire = new Person("Claire", Peter);

            Person Nathan = new Person("Nathan", null);
            Person Matt = new Person("Matt", Nathan);

            using (ISession session = OpenSession())
            {
                session.SaveOrUpdate(Claire);
                session.SaveOrUpdate(Matt);

                session.Flush();

                IList<Person> Peters;

                ICriteria crit = session.CreateCriteria(typeof(Person));
                crit.Add(NHibernate.Criterion.Expression.Eq("_name", "Peter"));
                IList<Person> p = crit.List<Person>();

                Console.WriteLine(p.First()._name);

                session.Delete(p.First());
                session.Flush();
            }
        }

        public static ISession OpenSession()
        {
            ISession session = null;

                try
                {
                    log4net.Config.XmlConfigurator.Configure();
                    Configuration cfg = new Configuration().Configure();
                    session = cfg.BuildSessionFactory().OpenSession();
                }
                catch(Exception ex)
                {
                    if (null != ex.InnerException)
                    {
                        Console.WriteLine(ex.InnerException.Message);
                    }
                    else
                    {
                        Console.WriteLine(ex.Message);
                    }
                    return null;
                }
            return session;
        }
    }
}


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 6:15 am 
Newbie

Joined: Mon Nov 02, 2009 9:52 am
Posts: 19
any ideas?


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 6:49 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
You also cascade to the parent, that makes no sense here (at least for delete):

<many-to-one name="_parent" column="parent" class="NewNHibernate.Person" cascade="all-delete-orphan"/>

Remove the cascade or change it to something that does not cascade deletes.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 7:20 am 
Newbie

Joined: Mon Nov 02, 2009 9:52 am
Posts: 19
ok,

I've removed the cascade.
Code:
<many-to-one name="Company" column="CompanyId" />


Now I'm getting a TransientObjectException on my last session.Flush().
Can you give me the right direction, again?


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 7:26 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Is there an inner exception or a meaningful message in the exception ?

_________________
--Wolfgang


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 7:37 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
You have to remove the child from the parent by yourself (that's part of the business model, not part of the persistance layer).

p.First().Parent.Remove(p.First());
p.First().Parent = null;

_________________
--Wolfgang


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 8:16 am 
Newbie

Joined: Mon Nov 02, 2009 9:52 am
Posts: 19
ok, this was one of the issues, I was NHibernate evaluating for.
But what is then the meaning of cascade=all-delete-orphan?

I thought it would delete the children automatically, when I delete the parent!?


Last edited by mosdev on Tue Nov 17, 2009 8:35 am, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 8:34 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Yes, but you said you were deleting the child (Claire), not the parent ! When you delete the parent, everything should work with cascade, but when you want to remove a child, you have to remove it from the parent's collection.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 8:37 am 
Newbie

Joined: Mon Nov 02, 2009 9:52 am
Posts: 19
ok, that's right. Thank you. I have changed it and I am removing Claire form the children collection.
But I am still getting this error (references an unsaved transient instance).


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 9:02 am 
Newbie

Joined: Mon Nov 02, 2009 9:52 am
Posts: 19
I'm getting this error, becaus NHibernate does not save the parents of Claire. It only persists them if I save the cascade property, which I should delete first. So I am at the beginning again.

Just to clarify:
I want to create a bidirectional association. If I save a child, I want NHibernate to save the parents (the cascade attribute in my many-to-one tag in Person.hbm.xml).
I want NHibernate to delete all children, if I delete a parent node.


Top
 Profile  
 
 Post subject: Re: Cascade="all-delete-orphan"
PostPosted: Tue Nov 17, 2009 9:27 am 
Newbie

Joined: Mon Nov 02, 2009 9:52 am
Posts: 19
I got it!
I saved the cascade attribute in the many-to-one and wrote the following:

Code:
        static void Main(string[] args)
        {
            SavePersons();
            DeletePerson();
        }

        private static void SavePersons()
        {
            Person Adam = new Person("Adam", null);
            Person Peter = new Person("Peter", Adam);
            Person Claire = new Person("Claire", Peter);

            using (ISession session = OpenSession())
            {
                session.SaveOrUpdate(Claire);
            }
        }

        private static void DeletePerson()
        {
            using (ISession session = OpenSession())
            {
                ICriteria crit = session.CreateCriteria(typeof(Person));
                crit.Add(NHibernate.Criterion.Expression.Eq("_name", "Claire"));
                IList<Person> p = crit.List<Person>();

                Person first = p.First();
                first._parent.Children.Remove(first);
                first._parent = null;
                session.Delete(first);

                session.Flush();
            }
        }

        public static ISession OpenSession()
        {
            ISession session = null;

                try
                {
                    log4net.Config.XmlConfigurator.Configure();
                    Configuration cfg = new Configuration().Configure();
                    session = cfg.BuildSessionFactory().OpenSession();
                }
                catch(Exception ex)
                {
                    if (null != ex.InnerException)
                    {
                        Console.WriteLine(ex.InnerException.Message);
                    }
                    else
                    {
                        Console.WriteLine(ex.Message);
                    }
                    return null;
                }
            return session;
        }


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.