NHibernate will not delete an orphaned object

I have several classes that look like this:

public class Token
{
    public int Id
    {
        get;
        set;
    }

    public ITokenInstance Instance
    {
        get;
        set;
    }
}

public interface ITokenInstance
{
    int Id
    {
        get;
        set;
    }

    Token Token
    {
        get;
        set;
    }
}

      

and mapping files


<class name="Token" >
   <id name="Id" >
      <generator class="hilo" />
   </id>

   <any name="Instance" meta-type="class" id-type="Int32" cascade="all-delete-orphan">
      <column  name="instance_type" />        
      <column name="instance_id" />
   </any>
</class>

<class name="TokenInstanceOne" >
   <id name="Id" >
      <generator class="hilo" />
   </id>

   <many-to-one name="Token" class="Token" column="token_id"/>
</class>

      

I have different implementations of the ITokenInstance interface, they all look in different tables, but they all use the same baisc structure as in the display. The problem is that for now I can add a new ITokenInstance to a token that has no instance (null) and it will update correctly. I can NOT add a new instance to a token that already has an instance and then update it, NHibernate will add a new instance that I provide, but does not delete the now unassigned instance. for instance

Token token = Session.Get<Token>(4);
var instance = Session.Get<TokenInstanceOne>(1);
Assert.AreSame(token.Instance, instance);

var newInstance = new TokenInstanceOne();
token.Instance = newInstance;
newInstance.Token = token;
instance.Token = null;
Session.Flush();

      

This calls SQL to insert a new TokenInstance and updates the token table to point to it, it does NOT delete the instance that was originally set to the token. Does anyone know how I can teach NHibernate to delete the original TokenInstance file from the database

Eidt: I missed something that is now included in the sample code (setting the original TokenInstance Token reference to null). Also just to clarify what SQL NHibernate produces:

  • INSERT INTO TokenInstanceOne (token_id, Id) VALUES (@ p0, @ p1); @ p0 = '4', @ p1 = '32768'
  • UPDATE Token SET instance_type = @ p0, instance_id = @ p1 WHERE Id = @ p2; @ p0 = 'ClassLibrary1.TokenInstanceOne', @ p1 = '32768', @ p2 = '4'
  • UPDATE TokenInstanceOne SET token_id = @ p0 WHERE Id = @ p1; @ p0 = '', @ p1 = '1'

Note that the last update set token_id = '', I need NHibernate to delete the row.

0


a source to share


2 answers


NHibernate does not implement what's called persistent garbage collection. There are situations when you need to explicitly delete objects. The cascade is used for the case when you remove the token.

This is your code:



var token = Session.Get<Token>(4);
Assert.IsNotNull(token.Instance);

// remove the old token
Session.Delete(token.Instance);

// assign the new token
var newInstance = new TokenInstance();
token.Instance = newInstance;
newInstance.Token = token;

// don't need to call update, the token is in the session.
// (except you turned off session flush)
// Session.Update(token);

      

+2


a source


Sorry, I misunderstood your question.

Have you tried setting inverse = "true" to either end? Alternatively move the cascade to a mapping of a different class.



Read

0


a source







All Articles