Root/Collection/Child Save Confusion

Root/Collection/Child Save Confusion

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


mcalhoun posted on Wednesday, June 16, 2010

Hi Everyone,

I'm working with CSLA 4 Beta 2 in a Silverlight environment and I've run into a situation where I'm unclear what the expected behavior should be.

I have a Tenant object (Editable Root). The tenant has a CustomerList (Editable Child Collection) that contains Customer (Editable child).

I use separate factory classes to create Tenant and Customer. Customer is marked as a child.

Here are my two points of confusion...

1. When I call BeginSave() on the Tenant (root) object, it is my understanding that BeginSave() should be called on each Child object as well. This doesn't appear to be happening for me. My "Update" method in the Customer factory is never being called.

2. How do I get data from the Tenant (root) to each of the Customer objects in the collection so I can use the TenantId as a foreign key in the Customers table in the db?

If anyone could provide a sample of this code working (or point me to one of Rocky's where it's working) it would be greatly appreciated!

Thanks,
Matt

Marjon1 replied on Wednesday, June 16, 2010

You need to make sure that the CustomerList is also being marked as a child.
Depending on if you always fetch the list or create would be done by using the DataPortal.FetchChild or DataPortal.CreateChild on the list itself.

Then as part of your Tenant object in the Dataportal_Insert / Update methods you need to make sure you that you call FieldManager.UpdateChildren()
This will only work if you are not using private backing fields, but as you are using silverlight I would imagine you aren't doing this. 

You could then make the call passing in the your Tenant object, like the following FieldManager.UpdateChildren(me)

Inside your Customer object your methods to do insert/updates might look like this:

Private Sub Child_Insert(ByVal parent as Tenant)

'Do whatever you need and you can access the id property from the tenant object

End Sub

 

Private Sub Child_Update(ByVal parent as Tenant)

'Do whatever you need and you can access the id property from the tenant object

End Sub

This should get your customer objects being updated correctly. Children objects are never saved in the same way that a root level object is. You either need to manually call methods (old CSLA method) to do the updates and then mark the objects as old, etc or use Child_Insert/Update & FieldManager.UpdateChildren() mechanism. The latter is the preferred and much easier option.

mcalhoun replied on Thursday, June 17, 2010

Hi Marjon,

Thanks for your reply!

First, I did forget to mention in my original post that CustomerList is also being marked as a child by using the DataPortal.CreateChild<CustomerList>(); method. You are also correct that I am not using private backing fields.

I think we have a little bit of a disconnect, as I am using separate Factory classes for Tenant and Customer. This means that I don't have access to the FieldManager in my Update method of TenantFactory as FieldManager is a protected property on the BusinessBase class.

My design goal is not to have any Data Access code in my business objects, so this is why I have chosen to use separate factories. I am also using Dependency Injection to load different factories and different repositories for test purposes, so moving all of that code back into the business object is not desireable.

Is there an other way to accomplish the Save on child objects and to pass the parent data down?

Thanks,
Matt

Marjon1 replied on Thursday, June 17, 2010

Matt,

I've not used the object factory pattern before, and attempted to see if there was any examples of how to do this in the CSLA videos but was unable to find anything. However, you should be able to do the following instead of using the FieldManager and given what I know about the additional work required when using the object factories, I'm guessing is the right way to go. 

Inside your factory class for tenant you would then need to do, essentially manually call the data-portal for each child that you have, e.g:

     DataPortal.UpdateChild(Customers, Me)

Based on what I understand your factory class for customer should then be called, assuming that it is dirty, etc.

Anyone else please feel free to correct any mistakes that I have made.

Copyright (c) Marimer LLC