I have a one-to-many relationship and cannot get cascade to work, once I set cascade I just get "object references an unsaved transient instance ...".
My mapping looks like this
public class SharedDetailsMapping : ClassMap<SharedDetails>
{
public SharedDetailsMapping()
{
Id(x => x.Id).GeneratedBy.Identity();
HasMany(x => x.Foos);
}
}
public class FooMapping : ClassMap<Foo>
{
public FooMapping()
{
Id(x => x.Id).GeneratedBy.Identity();
References(x => x.SharedDetails).Cascade.SaveUpdate();
}
}
The classes like this
public class Foo
{
public Foo()
{
SharedDetails = new SharedDetails();
SharedDetails.Foos.Add(this);
}
public Foo(SharedDetails sharedDetails)
{
SharedDetails = sharedDetails;
SharedDetails.Foos.Add(this);
}
public virtual Guid Id { get; set; }
public virtual SharedDetails SharedDetails { get; set; }
}
public class SharedDetails
{
public SharedDetails()
{
Foos = new List<Foo>();
}
public virtual Guid Id { get; set; }
public virtual IList<Foo> Foos { get; set; }
}
I then want to create Foos without having to save the SharedDetails first if its a new Foo, like so:
using (var transaction = _session.BeginTransaction())
{
var shared = new SharedDetails();
var fooOne = new Foo(shared);
_session.SaveOrUpdate(fooOne);
var fooTwo = new Foo(shared);
_session.SaveOrUpdate(fooTwo);
transaction.Commit();
}
Cannot figure out what I have done wrong, it works ofcurse if I save the SharedDetails first but that is why I have Cascade setup.
In your SharedDetailsMapping
, modify your HasMany
to add .Inverse()
:
public class SharedDetailsMapping : ClassMap<SharedDetails>
{
public SharedDetailsMapping()
{
Id(x => x.Id).GeneratedBy.Identity();
HasMany(x => x.Foos)
.Inverse();
}
}
This instructs NHibernate that Foo
owns the relationship, which will help it save objects in the relationship in the right order (in this case, the SharedDetails
has to get saved first so we have its ID when Foo
is saved).
Further info on the purpose/when to use Inverse: NHibernate's inverse - what does it really mean?
The TL;DNR version:
If you have a bidirectional relationship in your classes (HasMany on one side, References on the other), the HasMany should have .Inverse()
.