开发者

NHibernate cascading deletes in associated joined subclasses

I'm currently working on a small PoC project and decided to take NHibernate for a spin for the persistence part.

I have defined the following domain entities:

  • Location: abstract class representing a location (root of the location tree)
  • FixedLocation: abstract class representing a geographically fixed location (derives from Location)
  • Country: represents a country (derives from Location)
  • City: represents a city within a country (derives from Location and cannot logically exist without a Country)

Requirements:

  1. All locations must ultimately derive from Location (relationally, all Location descendants will share the same range of database keys)
  2. A bidirectional relationship should exist between Country and City
  3. Deletes should cascade throughout the entity tree, e.g. deleting a Country should also delete the associated Cities

Here's how I mapped the above classes

    <?xml version="1.0" encoding="utf-8" ?> 
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="AET.PoC.Domain" namespace="AET.PoC.Domain.Entities">    
    <class name="Location" table="Locations" abstract="true">
       <id name="Id" type="Int64" unsaved-value="0">
         <generator class="native" /> 
       </id>
       <property name="LocationType" access="readonly" /> 
    </class>
    <joined-subclass name="FixedLocation" table="FixedLocations" extends="Location" abstract="true">
         <key column="LocationId" /> 
         <component name="GPSPosition" class="GPSPosition">
             <property name="Latitude" type="double" /> 
             <property name="Longitude" type="double" /> 
         </component>
    </joined-subclass>
 <joined-subclass name="Country" table="Countries" extends="FixedLocation">
  <key column="FixedLocation开发者_高级运维Id" /> 
  <property name="Name" length="50" not-null="true" /> 
 <set name="CitySet" cascade="all, delete-orphan" inverse="true">
  <key column="CountryId" foreign-key="FK_City_Country" on-delete="cascade" /> 
  <one-to-many class="City" /> 
  </set>
  </joined-subclass>
 <joined-subclass name="City" table="Cities" extends="FixedLocation">
  <key column="FixedLocationId" /> 
  <many-to-one name="Country" class="Country" column="CountryId" not-null="true" cascade="all, delete-orphan" /> 
  <property name="Name" length="50" not-null="true" /> 
  </joined-subclass>
  </hibernate-mapping>

Mapping these classes this way fullfils the above requirements, or at least partially...

When I Delete() a Country entity (say location ID 1) that has 2 associated City objects (say location IDs 2 and 3), this is what happens:

  1. The record with FixedLocationId=1 is deleted from the Countries table
  2. The records with FixedLocationId=2 and 3 are deleted from the Cities table
  3. The record with LocationId=1 is deleted from the FixedLocations table
  4. The record with Id=1 is deleted from the Locations table

So far, so good, but...

  1. The records with LocationId=2 and 3 are not deleted from the FixedLocations table
  2. The records with Id=2 and 3 are not deleted from the Locations table

What am I doing wrong here? Can this be done in the first place?

I tried setting the on-delete="cascade" attribute in the of the tags but that made NHibernate complain about circular cascading not being allowed...


Do not put cascades on many-to-one in City. Instead make sure that every location knows about child locations:

<class name="Location" table="Locations" abstract="true">
    ....
    <many-to-one name="_parent" column="ParentLocationID" />
    ....
    <set name="_childLocations" table="Locations" inverse="true" cascade="all-delete-orphan" >
        <key column="ParentLocationID" />
        <one-to-many class="Location"/>
    </set>
    ....
</class>

This way you have your hierarchy and objects life cycle working and cascaded properly. You can take of other requirements in subclasses.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜