The exception thrown and the story described do not match together. Because the exception:
object references an unsaved transient instance ...
... Type: iProduct.City, Entity: iProduct.City
Says: There is a new instance of the City, referenced by CaseIndividual
, when the
...
_session.Save(individual);
transaction.Commit();
is called. Other words, to get this type of exception the code had to look like this:
var city = new City(); // or other way how to get reference (not null)
...
individual.City = city;
What does it mean? If we do not want to assign the existing City (already persisted, the one returned by the mapped view
) - The code must look like this:
...
individual.City = null; // here we go
_session.Save(individual);
transaction.Commit();
And the above code snippet, will never throw "..unsaved transient instance..." exception, because there is none passed to session. There is no need for a special Mapping of the CaseIndividualMap
, but...
Unsaved-value and City mapping
The Id
of the entity City
is mapped as Code. I guess, it is not of int
type. It would be a string
/varchar
.
Now, NHibernate must now, if the incoming instance of a City
is already persisted or if it is representing "new" (transient) instance. To make it easier and explicit, we have to extend the "id" mapping of a City
:
public CityMap() { Table("vCities"); ... Id(x => x.Code) .Column("Code") .GeneratedBy.Assigned() // NHibernate expects that ID is managed by us .UnsavedValue("verydummyvalue or even null")
Read here more about defaults of the unsaved-value: 9.4.2. Updating detached objects
The trick above, the assinged id and/or unsaved-value are correctly instructing NHibernate:
When individual is coming, with assigned City.. which id (i.e.: code) differentiate from
unsaved-value
... do expect it is not transient - do not try to INSERT it