CSLA .NET FAQ

It is often the case that a tree is best represented as a set of read-only objects, not editable objects. In other words, ROLB instead of BLB.

You can then have a set of Command objects that are used to perform operations on the read-only objects. The Command object can change the server-side data (in the database) and if that succeeds it can alter the client-side object graph (or at least coordinate the updates to the object graph - I'm not advocating breaking encapsulation).

As a brief example, suppose I have ListA and ListB. The UI allows the user to move items from one list to the other, and these changes are immediate (no 'Save' button - the move is auto-committed to the database). If you implement both lists as ROLB, their implementation is pretty easy, as is the UI.

When the user drops an item from B into A, the UI can invoke an AddFrom() command:

_listA.AddFrom(_listB, item);

or something like that. This AddFrom() method would invoke a Command object to do the actual work:

public void AddFrom(ListType list, ItemType item)
{
  ItemMover.DoMove(this, list, item);
}

the Command object is ItemMover, and would look like this pseudocode:

[Serializable]
internal class ItemMover : CommandBase
{
  // declare id key value properties here

  public static void DoMove(
    ListType fromList, ListType toList, ItemType item)
  {
    var cmd = new ItemMover {
      FromListId = fromList.Id,
      ToListId = toList.Id,
      ItemId = item.Id };
    DataPortal.Execute(cmd);

    // we get here because the server update worked
    fromList.RemoveMovedItem(item);
    toList.AddMovedItem(item);
  }

  protected override void DataPortal_Execute()
  {
    // update database to reflect change by using
    // the id key value properties

    // throw exception if this can't be done
  }
}

Note that this does require that you implement internal RemoveMovedItem() and AddMovedItem() methods on your read-only list class. These would look like this:

internal void RemoveMovedItem(ItemType item)
{
  IsReadOnly = false;
  try
  {
    this.Remove(item);
  }
  finally
  {
    IsReadOnly = true;
  }
}

This technique means you don't break encapsulation on any object. It provides a model by which you can implement discrete methods on what would otherwise be read-only lists, and is often the best model for implementing things list selection lists, treeviews and so forth.

All content and CSLA .NET is Copyright © 2009-2011 Marimer LLC