views:

695

answers:

2

I'm a newbie in the NHibernate world.

Why this code works removing the territory from the collection:

Country country;

using (IUnitOfWork unit = UnitOfWork.Start())
{
    country = new Country();
    country.Name = "My country";

    Territory territory = new Territory();
    country.Territories.Add(territory);
    country.Territories.Remove(territory);
}

And this code is not working:

Country country;

using (IUnitOfWork unit = UnitOfWork.Start())
{
    country = _countries.GetById(1);

    Territory territory = new Territory();
    country.Territories.Add(territory);
    country.Territories.Remove(territory);
}

In the second code snippet, _countries is a repository. The country ID 1 exists in the database. The territory is added, but never removed...

Here's the mapping:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="iCible.Artishows.Framework.ObjectDefinition"
                   namespace="iCible.Artishows.Framework.ObjectDefinition" >
  <class name="Country" >
    <id name="ID">
      <generator class="identity"/>
    </id>
    <property name="Name" />
    <set name="Territories" cascade="all-delete-orphan" inverse="true" order-by="Name" sort="iCible.Artishows.Framework.ObjectDefinition.TerritoryComparer">
      <key column="COUNTRYID"/>
      <one-to-many class="Territory"/>
    </set>
    <property name="CreationDate" />
    <property name="EditionDate" />    
    <many-to-one class="User" name="CreationUser"/>
    <many-to-one class="User" name="EditionUser"/>
  </class>
</hibernate-mapping>

What am I missing here?

+2  A: 

I struggled with a similar but different NHibernate problem with children not being deleted. The answer to my question might give you some insight, even if it's not exactly the same issue.

Eric J.
Thanks. I'll take a look at this when I'll be at work.
vIceBerg
+1 This helped me get on the right track.
JasonCoder
+1  A: 

I'm not entirely clear on the reason why, but I think it might be because of the inverse="true" part. The implication of having that, I think, is that it means the relationship is managed by the other side, i.e. from the Territory to the Country, so deleting the item from the Country.Territories may not work exactly as you expect.

What does your Territory mapping look like? - I assume it has a many-to-one reference to the Country parent?

Having said that, my NHibernate knowledge is still mostly at the level of "fiddle with the settings until it works like I want it to". But I'm pretty sure you'll be able to make it work by adjusting either the inverse attribute and/or the cascade option (i.e. try changing it to "all").

For what it's worth, most of our mappings that use one-to-many look like this, and I think we usually delete things in the same way as you showed:

<class name="Parent">
  <id name="ParentID">
  ...
  <map name="ChildCollection" cascade="all" inverse="true">
</class>

<class name="Child">
  ...
  <many-to-one name="Parent" column="ParentID" not-null="true">
</class>
Gavin Schultz-Ohkubo
Thanks. I'll take a look at this when I'll be at work.
vIceBerg