This seems like a super obvious question, but I haven't been able to find a clear answer. I'm using FluentNHibernate automapping with the DefaultCascade.All() convention.
Entities are saving, but in one-to-many relationships I'm having to provide the one side on my many side even though i'm saving by adding to a collection. An example will probably explain this better:
Lets say I've got these two classes:
public class Owner
{
public virtual IList<PetDog> Dogs { get; set; }
}
public class PetDog
{
public virtual Owner Owner { get; set; }
}
In order to add a new PetDog to the Dogs collection on an owner, I feel like I should be able to call
Owner.Dogs.Add(new PetDog());
and dispose my ISession. However, I'm just getting the Owner saving and thats it. If I explicitly set
Owner.Dogs.Add(new PetDog { Owner = Owner })
It works.
Is there a way to avoid explicitly providing that value?
This can be done by marking the Owner class as the owner of the relationship by setting inverse = false in the Owner mapping, i.e.
HasMany(x => x.Dogs)
.Not.Inverse()
.Cascade.AllDeleteOrphan();
Then the owner_id foreign key in the PetDog table will be populated on commit, i.e.
using (var transaction = session.BeginTransaction())
{
var order = new Owner() {Dogs = new List<PetDog>()};
order.Dogs.Add(new PetDog() );
order.Dogs.Add(new PetDog() );
session.Save(order);
transaction.Commit();
}
Alternatively, instead of using transaction you can call session.Flush()
instead which will cause the new data to be inserted into the DB, i.e.
var order = new Owner() {Dogs = new List<PetDog>()};
order.Dogs.Add(new PetDog() );
order.Dogs.Add(new PetDog() );
session.Save(order);
session.Flush(); // data persisted to DBMS here.
Please note that the use of session.Flush()
is not recommended best practice. It is recommended that explicit transactions are used. Please see this blog post by Ayende Rahien for further details.