views:

31

answers:

2

I'm trying to map a parent-child relationship using NHibernate (2.1.2), MySql.Data (6.2.2) and MySQL Server (5.1). I figured out that this must be done using a <bag> in the mapping file. I build a test app which is running without yielding any errors and is doing an insert for each entry but somehow the foreign key inside the children table (ParentId) is always empty (null).

Here are the important parts of my code...

Parent

public class Parent
{
    public virtual int Id { get; set; }
    public virtual IList<Child> Children { get; set; }
}


<class name="Parent">
  <id name="Id">
    <generator class="native"/>
  </id>        
  <bag name="Children" cascade="all">
    <key column="ParentId"/>
    <one-to-many class="Child"/>
  </bag>    
</class>

Child

public class Child
{
    public virtual int Id { get; set; }
}

<class name="Child">
  <id name="Id">
    <generator class="native"/>
  </id>    
</class>

Program

using (ISession session = sessionFactory.OpenSession())
{                                
     session.Save(
        new Parent() 
        {
            Children = new List<Child>() 
            { 
                new Child(), 
                new Child() 
            } 
        });
}

Any ideas what I did wrong?

A: 
<class name="Child">
  <id name="Id">
    <generator class="native"/>
  </id>    
  <many-to-one name="Parent" column="ParentID"/>
</class>
Charlie Brown
This wont help me because I want to map a list of child to a parent - not the other way around.
Martin
That's why I have a many-to-one in there. Child is the many side, Parent is the one side. In all our mappings, we specify both sides and it works.
Charlie Brown
+1  A: 

You must wrap all your data access in a transaction. This will work:

using (ISession session = sessionFactory.OpenSession())
using (ITransaction tx = session.BeginTransaction())
{                                
     session.Save(
        new Parent() 
        {
            Children = new List<Child>() 
            { 
                new Child(), 
                new Child() 
            } 
        });
     tx.Commit();
}

In fact, the inserts are only being performed because you're using a native generator; with a client-side generator they wouldn't even be sent to the DB.

Diego Mijelshon
I do not need to use a transaction. Its the implicit call of ISession.Flush() from ITransaction.Commit() that made your code work. For more details see: http://nhforge.org/doc/nh/en/index.html#manipulatingdata-flushing
Martin
That's true, but you DO need to use transactions. Please read http://ayende.com/Blog/archive/2008/12/28/nh-prof-alerts-use-of-implicit-transactions-is-discouraged.aspx
Diego Mijelshon