views:

946

answers:

2

I think I have tried every thing to get this to work but to no avail. Any hints/help much appreciated.

The following parent-children relationship causes the following error on creation of the parent.

could not insert: [Kanpeki.Domain.CalEvtCatergory][SQL: INSERT INTO tb_calEvent_catergory (catergoryID, parentID, catergoryType, catergoryLabel, id) VALUES (?, ?, ?, ?, ?)]

The 2 object mappings are as follows:

Parent = CalEvent

  <id name="id" column="id">
  <generator class="hilo"/>
</id>

<bag name="catergories" table="tb_calEvent_catergory"  lazy="false" cascade="all">
  <key column="parentID" foreign-key="id"/>
  <one-to-many class="CalEvtCatergory"/>
</bag>

Child = CalEvtCatergory

  <class name="CalendarCatergory" table="tb_calendar_catergory" lazy="false" >

<id name="id" column="id">
  <generator class="hilo"/>
</id>

<property name="parentID" />
snip....

It doesn't seem to be applying the (parentID) id of the calEvent to the CalendarCatergory

A: 

What does your c# (or vb) code look like when you are creating the new category?

Andrew Burns
+3  A: 

It sounds like it's probably trying to insert a NULL into a parent_id column on the child table that is marked as not null. There are two things you should do that will (probably) fix your problem. First, change

<property name="parentID" />

to

<many-to-one name="parentID" column="parent_id_column_name_here" not-null="true" />

Then, mark the relationship as inverse (i.e. the child manages the state of the relationship via the parentID property) by adding inverse="true" to the bag on the parent like:

<bag name="catergories" table="tb_calEvent_catergory" inverse="true" lazy="false" cascade="all">
  <key column="parentID" foreign-key="id"/>
  <one-to-many class="CalEvtCatergory"/>
</bag>

Also, I'm not sure the bag mapping is correct. Specifically, the foreign-key attribute. I couldn't find this in the documentation. NHibernate probably just ignores it but I'd get rid of it. In general, bi-directional, one-to-many mappings should look like:

<!-- Parent Table Mapping -->
...
<set name="Children" inverse="true" [(optional)cascade="all|save-update|etc"]>
    <key column="parent_id" />
    <one-to-many class="Child" />
</set>
...

<!-- Child Table Mapping -->
...
<many-to-one name="Parent" column="parent_id" not-null="true"/>
...

If you don't specify cascading, you have to save each object individually.

Stuart Childs
This could be spot on, I guess :)If you don't specify that the relation should be inverse, then NHibernate will first insert the child (with a NULL in the FK), then it will insert the parent (owner of the collection), and afterwards, it will UPDATE the child-record to set the FK relationship.
Frederik Gheysels
Yes, it's definitely a frustration for new NHibernate users (got me too). It makes sense from Hibernate's view that it needs to know that the child is managing the state with the parent id but it's counterintuitive since you usually think of the parent managing the child (from an object level view).
Stuart Childs