NHibernate: Id not updated on cascading save
I have a couple of domain objects which I am trying to save using the Cascade functionality. However, when I add a child to a parent and save the parent, the child object is not saved.
Update: The original version of the code here did not flush the session, which could have explained the behavior I saw. It didn't, however, and I've updated the code in the quesiton to better reflect the actual situation.
This is what I do in my controller and repository:
// in controller
public ActionResult AddChildToParent(int id /* of parent */, ChildInputModel input)
{
var child = GetChildFromInputModel(input); // pseudo
var savedchild = _repo.AddChildToParent(c, id);
// savedchild.Id is still 0, and nothing has been saved to the database.
return View(savedchild);
}
// in repo
public IChild AddChildToParent(IChild c, int parentId)
{
var parent = GetParentById(parentId);
var child = new Child();
c.CopyValuesTo(child); // A utility function in our library
parent.AddChild(child);
// These two calls might be unnessesary, but I'm keeping them here to sho
// my current code situation
var session = GetNHibernateSession();
session.Save(parent);
return child;
// session flushes when method returns thanks to injected transactions
}
I don't see the error in my application until I'm redirected to the edit page and the ID is 0, but I've verified in the database that no child record is added. I'm not changing anything else on the parent - just adding a child.
What am I doing wrong here?
These are my entities and maps (simplified):
public class Parent : IParent // Interface just defines everything public
{
public int Id { get; set; }
public string Name { get; set; }
private IList<Child> _children;
public IList<Child> Children
{
get
{ return _children ?? (_children = new List<Child>()); }
}
public void AddChild(Child c)
{
this.Children.Add(c);
c.Parent = this;
}
}
public class ParentMap : ClassMap<Parent>
{开发者_C百科
public ParentMap()
{
Id(p => p.Id);
Map(p => p.Name);
HasMany(p => p.Children).Cascade.AllDeleteOrphan().Not.LazyLoad();
}
}
public class Child : IChild // Interface just defines everything public
{
public int Id { get; set; }
public string Name { get; set; }
public Parent Parent { get; set; }
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
Id(c => c.Id);
Map(c => c.Name);
References(c => c.Parent).Not.Nullable();
}
}
That's normal: cascades are not stored immediately. The children get the ids after the next flush (which may take time, so don't flush explicitly after each call to AddChild
) or after explicitly saving the child.
var parent = GetParentById(parentId);
var child = new Child();
c.CopyValuesTo(child); // A utility function in our library
parent.AddChild(child);
var session = GetNHibernateSession();
// no need to save the parent, since it is already in the session.
// you may optionally save the child when the id is used in the code
session.Save(child);
精彩评论