Reputation: 2061
I have a few 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 various implementations of the ITokenInstance interface, all looking in different tables but all using the same baisc structure as shown in the mapping. The problem is that whilst i can add a new ITokenInstance to a Token that has no instance set (null) and it will update correctly I can NOT add a new Instance to a Token that has already got an instance and then Update it, NHibernate will add the new instance i provide but not delete the now un-assigned instance. For example
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 fires SQL to insert the new TokenInstance, and updates the token table to point at it, it does NOT delete the instance that was originaly set to the token. Does anyone know how I can instruct NHibernate to delete the original TokenInstance from the database
EIDT: I had missed something off that is now included in the code example (setting original TokenInstance's Token reference to null). Also just to clarify this is the SQL NHibernate is producing;
Notice the last Update is setting token_id = '', what i need is for NHibernate to delete the row instead.
Upvotes: 0
Views: 1635
Reputation: 64628
NHibernate does not implement a so called persistent garbage collection. There are situations where you need to remove entities explicitly. The cascade is for the case when you delete 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);
Upvotes: 2
Reputation: 27374
Sorry, I misunderstood your question.
Have you tried setting inverse="true" on your any end? Alternatively move the cascade to th the other class' mapping.
Upvotes: 0