views:

47

answers:

2

I want to be able to create a parent object with children and let the parent handle the update, saves and deletes.

My map classes.

ParentMap

    Id(x => x.Id, "ID").GeneratedBy.Identity();
        Map(x => x.Name);                

        HasMany(x => x.Children)
            .KeyColumn("ParentID")
            .Inverse()
            .Cascade
            .AllDeleteOrphan()
            .AsBag();

ChildMap

Id(x => x.Id, "ID").GeneratedBy.Identity();
Map(x => x.Name);            
Map(x => x.Value);            
References(x => x.Parent);

This is the code.

After the postback I create a new parent with children. The problem is it won't delete the children but everything else works fine update and saves.

var parent = new Parent();
parent.Id = _view.parentID;
parent.Name = _view.Name;
parent.Children = _view.Children; 

I've also tried the code below but this returns a nonunique error.

var parent = repository.Get(_view.parentID);
parent.Name = _view.Name;
parent.Chidlren = _view.Children;

Can anyone tell me the best way to deal with this in NHibernate?

Thanks.

A: 

Try clearing the Children collection first:

var parent = new Parent();
parent.Id = _view.parentID;
parent.Name = _view.Name;
parent.Children.Clear();
parent.Children = _view.Children;

I'm not sure that reassigning the collection is a good practice. I recommend clearing the collection then looping through _view.Children and adding each child. Better yet, use the IEnumerable Except extension method to determine which children need to be added or removed and handle those individually.

Jamie Ide
Thanks for the quick reply.I've tried the above it returns a NotUniqueException. Do you have any examples of the IEnumerable Except extension?Thanks.
Calum Bett
+2  A: 

You can't reassign the child collection with NHibernate. NHibernate is basically "watching" the child collection for changes so that it knows how to handle saves to the database. If you reassign the child collection NHibernate looses the reference and can no longer track the changes. To get around this you must modify the child collection but not reassign it.

How I normally ensure this is I make the collection readonly with a private setter. I then add methods to the parent class to modify the list as needed.

private IList<ChildRecord> theChildCollection = new List<ChildRecord>();
/// <summary>
/// The collection of child records.
/// </summary>
public virtual IList<ChildRecord> Children
{
   get
   {
      return theChildCollection.ToList().AsReadOnly();
   }
   private set
   {
      theChildCollection = value;
   }
}

/// <summary>
/// Adds a record to the child collection.
/// </summary>
public void Add(ChildRecord aRecord)
{
   theChildCollection.Add(aRecord);
}

/// <summary>
/// Removes a record from the child collection.
/// </summary>
public void Delete(ChildRecord aRecord)
{
   theChildCollection.Remove(aRecord);
}
brainimus
Looks like a good solution I'll modify my code. The only problem is finding out which children to add, update and delete when I'm dealing with two lists one with the old chidren (from db) and the other list with the modified children (from user input). Do you know a way of doing this without looping through the lists?Thanks.
Calum Bett
Calum -- please add that as a new question.
Jamie Ide