Editable Root List Question

Editable Root List Question

Old forum URL: forums.lhotka.net/forums/t/6369.aspx


Ian posted on Saturday, February 07, 2009

I'm stuck on something I'm hoping you can help with. I have a Customer object (BB) that contains an ERLB called

Notes that contains root Note objects (BB). My intention is to load all of the customer's notes as children, but

have them save themselves to the database, which ERLB provides. In addition, when a new note is created, I want

the Notes collection to automatically be updated to include the new Note, which ERLB also provides through the

SaveItem method.

Now, I know the ERLB was made specifically for editing the root objects in a grid, but its functionality is exactly

what I want even though I don't want to use a grid. Unless I'm mistaken, BLB doesn't provide a SaveItem equivalent, so "children" that save themselves don't automatically update the parent collection.

On the customer edit screen, I'd like to show the list of notes, loaded when the customer is loaded. Clicking on a

note will open the note in a note edit screen. So the note object itself will be passed to the form. When the

user clicks Save on the note edit screen, the note will save itself to the database. The dilemma I have is that

the note object does not have a reference to its parent collection (it's a root, not a child) so it can't call the

parent collection's SaveItem method. Now, I could override the Save method for the note object itself, but I would

still need a reference to the Notes ERLB.

I could implement the plumbing myself, creating my own "AddChild" method and creating a non-serializable reference, but I expect it already exists in CSLA somewhere and I just haven't found it.

rsbaker0 replied on Saturday, February 07, 2009

I think objects in an ERLB actually do maintain a reference to the parent list, via the Csla.Core.IParent interface. It seems to be protected, but it would be available to a derived BusinessBase<T> class.

Ian replied on Sunday, February 08, 2009

Ok here's what I tried:

In the Note object:


public override Note Save()
{
Csla.Core.IParent parent = this.Parent;
parent.??? - what do I call here?

//return base.Save();
}


My first problem with this is that the IParent interface does not have the SaveItem method I'm looking for. And the ApplyEditChild method does not return a Note object like the Save method does.

My second problem is that this.Parent is null. To try to fix this, in my Notes collection I have in DataPortal_Fetch:


using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader()))
{
while (dr.Read())
{
Note note = new Note(dr);
// set Notes collection as parent somehow
Add(note);
}
}


I'm not sure how to provide the parent reference to the Note object.

rsbaker0 replied on Sunday, February 08, 2009

Well, if you "know" what the IParent is supposed to be, you could cast it to the correct type and then call Save Item on it. e.g.

MyParentList list = this.Parent as MyParentList;

In my case, I have intermediate base classes between all my classes and CSLA, so I have implemented a set of interfaces to help. It may be that a useful interface is already available here for casting (but I'm not in front of my source code at the moment)

I'm not sure why your parent is null. Let me take a look at this tomorrow at the office and see where I see the Parent being populated for and EditableRootListBase derived class and child.

rsbaker0 replied on Monday, February 09, 2009

OK, I've looked further, and ERLB appears to call SetParent() on the "child" objects in the list in:

(1) InsertItem, as items are being added

(2) SetItem(), when an item is being replaced in the list

(3) OnDeseserializedHandler(), when the object is being deserialized (e.g. fetched over the data portal?)

Ian replied on Monday, February 09, 2009

Aha!  I believe you have solved one of my problems.  I was calling the Add method to load items into the list instead of InsertItem.  I'm willing to bet that the parent reference is set now. 

But somehow I got stuck trying to get the parent reference in the Note's Save method.  When I started this thread over the weekend from home, I swear this code compiled (although it was evaluated to null):

public override Note Save()

{

Csla.Core.IParent parent = this.Parent;

...

}

Now that I'm back at work this does not compile as the Note object, which is derived from BusinessBase<Note>, does have have a Parent property.  I see the protected internal version in the Core.BusinessBase class, but it is not available to my Note object.  I have no idea why it worked at home but not here.

I should note I'm using CSLA version 3.6.0.

rsbaker0 replied on Monday, February 09, 2009

Hmmm. I'm on CSLA 3.5.1, and it's just "protected" in that version.

I pretty much *have* to have the capability to traverse the object graph in both directions, so if this is gone in CSLA 3.6, I'd just change the code.

Ian replied on Tuesday, February 10, 2009

It looks like it changed to protected internal in  Csla version 3.6.0.  However the reason I couldn't see it is something even simpler.  Apparently I had Hide Advanced Members unchecked at home but not at work.  It's amazing how quickly simple things can get solved after a good night's sleep. 

And as it turns out, overriding the Save method in Note is not a great idea since Notes.SaveItem() calls this method itself, and results in a loop.  I guess I'll have to write my own Save method that will call the parent's SaveItem method, which will in turn call the original Save method.  Due to the protection level of the Parent property, I can't call note.Parent.SaveItem(note) under the Save button on the form, so I'll need my own method.  C'est la vie.

Thanks for your help, by the way.

Copyright (c) Marimer LLC