Naganathan
Naganathan

Reputation: 181

NHibernate object references an unsaved transient instance save the transient instance before flushing

I am trying to save a complex object which has many referenced elements inside and it works perfectly most of the time.
However in some cases we are getting the below exception,

object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave. Type: Namespace.Core.Client.ClientDetails, Entity: Namespace.Core.Client.ClientDetails

The problem is, there are around 12 ClientDetails elements inside my complex object which we are trying to save.Is there a way to identify which object instance caused this issue? through NHibernate logging or some other way? My code sample used for save as below,

_repository.Save<SuperParent>(obj);
_repository.Flush();

Please note when i set the Nhibernate show_sql to true i am able to see all the queries properly generated, but when the flush is called, the exception is thrown.

Please help to resolve the issue.

Upvotes: 18

Views: 34839

Answers (4)

Michael Todd
Michael Todd

Reputation: 11

This error also happens when you have a complex object that includes children that are reference data (think ClientType class). If the child has a version element in it's mapping file that maps to an int column in your database, the version number for an existing row should never be set to 0. Nhibernate interprets this as an object to be inserted on a cascade update and will fail as it's attempting to insert a row that already exists.

Upvotes: 1

AmirHossein Rezaei
AmirHossein Rezaei

Reputation: 1400

Edit your mapping to cascade all changes.If you have a Client Class that have many ClientDetails , your xml mapping would be like this

In Client.hbm.xml file you should have :

<set name = "ClientDetails" table = "`ClientDetail`" cascade = "all-delete-orphan" inverse="true"> 
         <key column = "ClientId"/> 
         <one-to-many class = "ClientDetail"/> 
</set>

In ClientDetail.hbm.xml file you should have :

<many-to-one name = "Client" class = "Client" column = "ClientId " />

Upvotes: 1

BrennQuin
BrennQuin

Reputation: 664

If you read carefully:

...he transient instance before flushing or set cascade action for the property to something that would make it autosave

So, maybe you can add Cascade to the Reference, like this:

References(x => x.ClientDetails).Cascade.All().Column("ClientDetailsId")
                  .Not.Nullable();  //Or nullable, this depends on your schedule

Upvotes: 4

Firo
Firo

Reputation: 30803

The exception means that there is an unsaved instance of ClientDetails referenced by this object. You have to either save it manually before saving the parent

session.Save(Parent.SomeDetail);

or set Cascade.SaveOrUpdate on the reference-mappings in the parent mapping.

Upvotes: 16

Related Questions