Saving a single record using DataPortal_Update

Saving a single record using DataPortal_Update

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


Brownpa1 posted on Friday, January 09, 2009

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.

 

rsbaker0 replied on Friday, January 09, 2009

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.

DocJames replied on Saturday, January 10, 2009

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

SonOfPirate replied on Saturday, January 10, 2009

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.

DocJames replied on Sunday, January 11, 2009

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

SonOfPirate replied on Sunday, January 11, 2009

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.

 

ajj3085 replied on Monday, January 12, 2009

You may be interested in this thread, specifically this post from Rocky.

Copyright (c) Marimer LLC