Silverlight - BeginCreate vs CreateChild

Silverlight - BeginCreate vs CreateChild

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


AaronH posted on Monday, June 13, 2011

Why is DataPortal.CreateChild() synchronous while DataPortal.BeginCreate() is asynchronous.  What is the thought behind that design decision?

It's a bit confusing from a UI consumption standpoint.  For example, if I create a root, I expose a New method that returns void, but accepts a callback:

Root.NewRoot((s, e) => { _myRoot = e.Object}

However, when adding a child to the root, it's different, as creating a child via DataPortal.CreateChild():

Child child = Child.NewChild();  // Invokes DataPortal.CreateChild()

_myRoot.Children.Add(child);

This is very confusing.  Is there a better, more intuitive way to implement this?

Thanks!

RockfordLhotka replied on Monday, June 13, 2011

The data portal has two "modes": root and child.

Create, BeginCreate, Fetch, BeginFetch, Update, BeginUpdate, Delete, BeginDelete, Execute, and BeginExecute are all root methods - they operate on root objects.

The XyzChild methods are child methods - they operate on child objects.

Only root objects can be directly created, retrieved, updated, or deleted. Child objects are always created, retrieved, updated, or deleted by their parent - and that's ultimately controlled by the root.

This is described in the Using CSLA 4 ebook series, and the older Expert Business Objects books. The concept of a root vs a child object is central to the data portal and data access models supported by CSLA .NET.

RockfordLhotka replied on Monday, June 13, 2011

I suppose to more directly answer your question, I should point out that, in Silverlight, the data portal can be used in local or remote mode.

The reason the XyzChild methods exist in Silverlight is purely to support the local mode - where the root object of the object graph is being created/retrieved on the client (presumably by calling a service), and it then uses the results of the service call to populate itself and its child objects with data.

AaronH replied on Monday, June 13, 2011

Hi Rocky, this still doesn't explain why DataPortal.FetchChild() is implemented as a synchronous method within the Silverlight CSLA implementation.

Again, this is confusing behavior, as creating a new root object requires a callback function, and creating a new child object does not (because it's synchronous).  This leads to very different implementations behind the scenes, too.  For example:  

    public partial class Root
    {
        public static void NewRoot(EventHandler<DataPortalResult<Root>> handler)
        {
            // Create a new object, invoke business/auth rules, set default values, and return the new instance via callback
            DataPortal.BeginCreate(handler, DataPortal.ProxyModes.LocalOnly);
        }
    }

  public partial class Child
  {
     public static Child NewChild()
     {
         // Create a new object, mark it as a child, invoke business/auth rules, set default values, and return the new instance
         return DataPortal.CreateChild<Child>();
     }
 }
 

As you can see, the implementations of both are VERY different, as are the way they are consumed by the UI.  

Wondering:

1.) What the reasoning behind exposing CreateChild() as a synchronous method is
2.) Is there a better way to keep implementations and consumption patterns more consistent, 
but still gain the benefits of creating a root vs. child appropriately

RockfordLhotka replied on Monday, June 13, 2011

I guess I could have phrased that better.

Only the root data portal moves the call from the logical client to the logical server. The child data portal never crosses a layer/tier boundary.

That's true in .NET, and it is true in SL.

So your BeginCreate call moves from the logical client to the logical server. Starting at your DataPortal_Create method, all code is "server-side code".

All server-side code is synchronous - within the context of the server. Again, true on .NET and true on SL. The entire object graph must be created, populated, and fully established in memory before the server-side call (DataPortal_Create) completes.

Just think how much "fun" you'd have if the child data portal was async. You'd have to manually write threading code to ensure that the DataPortal_Create method didn't complete until all your async operations were done. And you'd have to do this without blocking the UI thread and locking the browser.

In .NET v.next this will be easier (with the new async/await features). But those new async features probably won't get to SL until SL6.

Ultimately, to avoid the nightmarish fallout of forcing everyone to write complex threading code to populate their object graphs when using the local data portal in SL - I made the SL child data portal work exactly like the .NET one.

Copyright (c) Marimer LLC