1

I have a problem concerning an inconsistency (in my program) on entity deletion using Nhibernate.

I have to store entities and binary relations that bond them.

Here is the model:

public interface IPersistent
{
    int ID { get ; set;}        
}

public virtual class Entity : IPersistent {
   //relations where the entity appears on the left side
   public ISet<Relation> LeftRelations  { get;}

   //relations where the entity appears on the right side
   public ISet<Relation> RightRelations { get;}       
}

public virtual class Relation : IPersistent {
   public Entity LeftEntity     { get;}
   public Entity RightEntity    { get;}
   public RelationType Type     { get;}

   // must be called before ISession.Delete()
   public void ClearRelation(){
        LeftEntity.LeftRelations.Remove(this);
        RightEntity.RightRelations.Remove(this);
        LeftEntity = null;
        RightEntity = null;
   }
}

my mapping looks like:

<class name="Entity" table="entity">
    <id column="id_entity" name"ID" unsaved-value="-1" type=Int32>
        <generator class ="native">
            <param name ="sequence">seq_task_id_entity</param>
        </generator>
    </id>
     <set name="LeftRelations" table ="relation" generic="true"
          cascade="all" inverse="true">
         <key column="left_entity"  foreign-key="id_entity"/>
         <one-to-many class ="Relation"/>      
     </set>
     <set name="RightRelations" table ="relation" generic="true" 
          cascade="all" inverse="true">
       <key column ="right_entity"  foreign-key ="id_entity"/>
       <one-to-many class ="Relation"/>      
     </set>
</class>

<class name="Relation" table="relation" >
    <id column="id_relation" name"ID" unsaved-value="-1" type=Int32>
        <generator class ="native">
            <param name ="sequence">seq_task_id_relation</param>
        </generator>
    </id>
    <many-to-one name ="LeftEntity" class="Entity"  cascade="all" 
                    update="true" not-null="true">
          <column name ="left_entity" sql-type="integer" not-null ="true"></column>
    </many-to-one>

    <many-to-one name ="RightEntity" class ="Item" cascade="all" 
                    update="true" not-null="true">
          <column name ="right_entity" sql-type="integer" not-null ="true"></column>
     </many-to-one>   
</class>

I can persist both entity and relation instances. When I delete a persisted entity (which is not bound to any relation), its ID property is updated to the unsaved-value after commit. But when I delete a persisted relation, the relation row in database is deleted, but the relation'ID property is not resetted to the unsaved-value.

Is this behavior normal? Or it is my nh mapping that is incorrect?

Cœur
  • 37,241
  • 25
  • 195
  • 267
tumasgiu
  • 325
  • 3
  • 11

1 Answers1

3

To answer this:

But when I delete a persisted relation, the relation row in database is deleted, but the relation'ID property is not resetted to the unsaved-value.

The unsaved-value is a setting used to compare. It is not inteded to set value.

NHibernate just needs this setting to understand if the entity passed to ISession should be treated as Transient or Existing in DB.

The unsaved-value is just a constant setting - used just for comparison and decision: is object transient or existing.

Documentation:

5.1.4. id

<id
    name="PropertyName"                      (1)
    type="typename"                          (2)
    column="column_name"                     (3)
    unsaved-value="any|none|null|id_value"   (4)
    access="field|property|nosetter|ClassName(5)">
    ...

...
(4) unsaved-value (optional - defaults to a "sensible" value): An identifier property value that indicates that an instance is newly instantiated (unsaved), distinguishing it from transient instances that were saved or loaded in a previous session.

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Understood. So there is no way to know if an entity has been deleted ? – tumasgiu Jan 19 '15 at 12:57
  • No... but. Each write operation should be wrapped inside of some transaction and after that we should close the session. Later, when we want to access some "changed" stuff we should (MUST) use new session without old objects in it. Always do your best to split WRITE and READ operations – Radim Köhler Jan 19 '15 at 13:10
  • So NH entities has to be viewed like DTOs ? – tumasgiu Jan 19 '15 at 13:19
  • NO - the transaction, operation, unit of work should be treated as atomic. 1) In one request/session/unit of work we change data. Close the session ... *remove all that stuff from session/memory* ... 2) Redirect to read operation - 3) open new session and read the latest data there. Does it help? – Radim Köhler Jan 19 '15 at 13:20