Using DataPortal_Update on a BusinessListBase, how can I save and close just a single child object that is within the collection without saving all other records?
I want the user to be able to save and close a single child in the collection without effecting the other members of the collection.
I'd argue that CSLA was not really intended to work this way and you should ask yourself why you want to do this, especially if this list is itself a child of another object.
That being said, I'm sure it's possible, especially if you have derived your own BusinessListBase class and have written your own save code. One possibility would be to somehow clone the object to be saved (and have it not be a child), and just explicitly save the clone and then update list object afterwards.
A list which does allow saving of individual members is the EditableRootListBase.
This is an example on how I do it:
I have a public class KontoList : BusinessListBase<KontoList, KontoChild>
containing the following methods:
#region SaveUpdated
public void SaveUpdated(KontoList kontoList)
{
// Get a list of the child object which needs to be created/updated/deleted
BusinessObjects.Finans.KontoList KontoplanSave = kontoList.GetListToSave();
// Create, update and delete objects
KontoplanSave = KontoplanSave.Save();
// Update List with created/updated/deleted objects
kontoList.SetListAfterSave(KontoplanSave);
}
private KontoList GetListToSave()
{
// Create Empty KontoList object to contain created/updated/deleted child objects
KontoList SaveKontoList = NewKontoList();
// Add created/updated child objects
foreach (KontoChild child in this)
if (child.IsSavable)
SaveKontoList.Add(child);
// Add deleted child objects
foreach (KontoChild deletedChild in DeletedList)
SaveKontoList.DeletedList.Add(deletedChild);
return SaveKontoList;
}
private void SetListAfterSave(KontoList savedList)
{
// Delete deleted child objects from the original List
// Should be done first (can't remember why)
foreach (KontoChild deletedChild in DeletedList)
Remove(deletedChild);
// Update the original list with the saved child objects
foreach (KontoChild savedChild in savedList)
{
// KontoGuid is the unique child key property
int Index = IndexOf(GetChildByGuid(savedChild.KontoGuid));
this[Index] = savedChild.Clone();
}
// Delete the list containing the objects to be deleted as they have been deletd now
DeletedList.Clear();
}
public KontoChild GetChildByGuid(Guid kontoGuid)
{
// KontoGuid is the unique child key property
foreach(KontoChild child in this)
if (child.KontoGuid == kontoGuid)
return child;
return null;
}
#endregion // SaveUpdated
I then simply call myKontoList.SaveUpdated(myKontoList); to save the updated children.
At the moment I have the same code in all my List classes. If anyone knows if it's possible (and how) to move the code into a class derived from BusinessListBase I would be really happy. I have not yet succeeded in getting it to work.
Thanks,
Jimmy
Wow! Seems pretty complicated for something that CSLA tries to manage for you.
The first question I'd ask is whether the item you are trying to save is the only one in the collection that is dirty. If it is, then no worries. The normal process used by the CSLA framework will only save/update items that are dirty. If not, then I'd ask why you are committing only one item when the collection contains others that are dirty? Perhaps you should be using editable child objects so that you can call Save directly on the item rather than saving the list.
For what it's worth, EditableRootListBase contains a SaveItem method that will allow you to save a specific item within the collection by index. You can also look at how this class uses the IsSavable flag to determine which items to save when the list is saved if you need an example.
I'm using the DataPortal and I want to avoid sending 10.000 rows over the wire when only updating 1-3 rows. My users need the data saved often (almost every row being updated) and not just when they leave the (Windows) form.
I do loop the whole collection looking for .IsSavable items which I add to a new collection which is the one being saved.
I actually haven't looked at EditableRootListBase which could be what I need. In the case of 2 or 3 rows needed update, I don't want to call the DataPortal 2-3 times.
Thanks,
Jimmy
Yep, you're absolutely right. The two limitations I've found with the CSLA implementations are exactly as you described: you are either sending the entire collection of hundreds or thousands of rows of data acrosse the wire to the Data Portal Server where it is enumerated and changes applied; or, you end up with multiple calls through the data portal.
If you are looking for an immediate save when the changes are committed to each row, then I think either having an editable child so that you can Save the individual item or using the EditableRootListBase where you can tell the list to save the item works best. If your users are making changes to multiple items then saving the batch at once, I agree that working with a subset is totally applicable.
I think LINQ could be used to simplify your code, though. I recently had a similar use case and implemented a GetChanges() method that used a LINQ statement to return all items that were marked as dirty. You could easily extend this with an additional Where statement checking that the items are savable.
Copyright (c) Marimer LLC