Vibrant discussion about CSLA .NET and using the framework to build great business applications.
I was going through the options how to enumarate through object's children with managed properties. As per Jonny's advise ( http://forums.lhotka.net/forums/t/11038.aspx ), FieldManager.GetChildren should accomplish it.
However, I was wondering why does it returns only IEditableBusinessObject and IEditableCollection objects?
In case of BusinessBase -> ReadOnlyBase aggregation, GetChildren method will not return ReadOnlyBase child.
This might be related to the fact that ReadOnlyBase and read-only lists are not so welcome as children in CSLA. Example of it is that they have no MarkAsChild implementations.
Rocky, any insight on the anticipated compositions between CSLA stereotypes?
It is not generally a good idea to have a read-only child contained in an editable parent. This is because child objects are part of the state of the parent, and when an editable root is saved the entire object graph is transferred to and from the server. As a result, your read-only child is transferred to/from the server and that's just a waste of bandwidth and serialization effort.
FieldManager.GetChildren returns the editable objects owned by this instance (owning reference) that must also be updated / saved.
A readonly base should never be saved - hence it doesn't matter if it is a child or not.
For editable objects you are only allowed to call Save on the "root" object - and if you call Save on an object that is child the DataPortal will throw an exception.
So an EditableObject may contain readonly objects - and it doesn't make sense to have MarkAsChild or even loop through it during a save as it is not a savable object.
ReadOnlyObjects are welcome as children.
Jonny Bekkum, Norway
If editable object -> read-only object(s) aggregation is allowed in CSLA then the goal I want to achieve is to enumerate through all managed properties of editable object (parent) and get all children whether editable or not.
It really has nothing to do with persistance mechanism. I completely understand that you can invoke Save only on the parent and that it's responsible to control the process. But in this case it should simply ignore read-only object(s) in its graph when saving, as it should do with n-level undo.
Also I don't see GetChildren method being used for update process but rather UpdateChildren method. It's interesting that BusinessBase uses GetChildren in its FieldDataDeserialized method to subscribe back certain events from its children. In this case, if editable object -> read-only object(s) is allowed I think it should take care about that kind of children for BusyChanged event hooks in particular.
Additionally ReadOnlyBase implements IManageProperties interface by calling FieldManager.GetChildren method for IManageProperties.GetChildren. This brings me to the question, what kind of parent/child relation is allowed when ReadOnlyBase is parent? Certainly, it should not be editable object(s) because there would be no parent to control the persistance. If so, then it looks like the only viable option is read-only object(s) as children, but in that case GetChildren will return empty list.
I would argue whether MarkAsChild on read-only object make sense because IsChild is very valuable context for a lot of logic beside persistance.
As you see the question is beyond object saving and more toward possible compositions within CSLA.
I'll appreciate if Rocky can provide some list of parent/child relations that work.
Thank you Jonny,
It shouldn't be hard to imagine scenarios that have editable parent and read-only stereotype as child or children.
The issue you described is well-known for non-dirty editable child as well. I used to solve it by having lazy-loaded child that's "nullified" if it's read-only or editable but non-dirty. Even if that part of graph is needed on the Data Portal, it usually is more efficient to fetch it from there than to carry it over network.
However, I didn't find a way to "nullify" child in FieldManager. There's RemoveField method, but that one is internal and still doesn't remove actual FieldData but rather set it's value to null.
Any guideline on how to reset lazy-loaded field if it's read-only or editable but non-dirty?
For "child" objects that aren't really part of the object graph I recommend using private backing fields instead of managed properties. This allows you to mark the private fields as NotUndoable and NonSerialized, easily preventing them from incurring all that overhead.
Speaking of private backing fields, can you specify what are pieces of functionality that need to be manually taken care of when using them?
As long as I see, dirtiness metastate (marking BO as dirty when such property is changed), authorization, broken rules and property changed notifications are all still supported.
Dirty is not tracked on the field level. IsDirty and IsValid have to be overriden. Updates won't be covered by invoking UpdateChildren on FieldDataManager. Those fields have to be explicitly set during serialization in SerializationInfo.
Is there anything else I'm missing?
I assume you've read the 'Using CSLA 4' books?