ApplyEdit vs BeginSave

ApplyEdit vs BeginSave

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


AaronH posted on Friday, April 02, 2010

When using BusinessBase in Silverlight, why would one choose ApplyEdit over BeginSave, vice versa?  ApplyEdit has no way of notifying a direct caller that the DP.Update() was successful like BeginSave can (via the delegate argument).  It seems that with ApplyEdit, you invoke and forget it.

AaronH replied on Friday, April 02, 2010

Ahh, I see what's going on.  ApplyEdit doesn't really invoke any kind of Update, it checks to see whether a parent exists, and that parent may or may not invoke a DP.Update.  This is the case of calling BusinessBase.ApplyEdit within the context of an EntityRootListBase (ERLB).

In a previous post, I have mentioned some of my struggles using a ERLB in conjunction with a ListBox.  I'm almost there, however, what I'm attempting to do is grab the selected bound EditableRoot, and pass it into a popup view.  When the user edits the ER and clicks "OK", I want the save to be successful before closing the popup and returning control to the view that launched it (the view containing the ListBox).

Problem is, when using an EditableRoot contained within an ERLB, it expects ApplyEdit to be invoked, and ApplyEdit follows a fire-and-forget approach.  So, unless I pass a reference to the entire ERLB to the popup, the popup will have no way of knowing whether the DP.Update was successful or not as a result of invoking ApplyEdit.

Anyone have any thoughts on this?

rsbaker0 replied on Friday, April 02, 2010

AaronH

...Problem is, when using an EditableRoot contained within an ERLB, it expects ApplyEdit to be invoked, and ApplyEdit follows a fire-and-forget approach.  So, unless I pass a reference to the entire ERLB to the popup, the popup will have no way of knowing whether the DP.Update was successful or not as a result of invoking ApplyEdit.

Anyone have any thoughts on this?

I think the Parent of your EditableRoot will be set to the ERLB, so at least in theory there is a way to get to it without explicitly passing a separate reference.  (Not sure if ERLB is necessarily the right choice here, but you can probably resolve this particular issue without redoing what you already have with another list type)

RockfordLhotka replied on Friday, April 02, 2010

As I mentioned once in the other thread, I'm not really sure you should be using ERLB. I'm just not sure it is making your life any easier, and it might be simpler to just retrieve a MobileList of root objects and then save them when you want to save them by calling BeginSave() on that item.

The only thing you need to handle in that case is to replace the old item in the list with the new item you get back from the server if the save is successful, so the list remains current with the actual item.

AaronH replied on Saturday, April 03, 2010

Rocky, could you point me to a demo that is currently using the MobileList of root objects?  I cannot find one.

I'm thinking either approach is a crap shoot at this point, however.  ERLB is REALLY nice, I have to say.  It's nice because the object reference to an edited object is properly updated in the bound list automatically.  Compare this to a ObservableCollection of EditableRoots, where you have to manually remove an EditableRoot from the bound list, remember its position, and insert the updated ER passed back from the server after a successful DP.Update.  Works, but it's a bit hackish as well.

So no perfect solution here.  So it's a struggle to choose the lesser of two evils: between manual manipulation of an underlying bound list (OB, MobileList, etc.), or passing around an ERLB reference to other views/viewmodels that need to be notified when a EditableRoot was successfully saved so that it can return control to the caller..

RockfordLhotka replied on Saturday, April 03, 2010

I don't have such a sample.

You are right about the implementation. MobileList<T> is just an ObservableCollection<T> that can flow through the Silverlight data portal. So it will take as much work to use as using a regular OC of root objects.

You'll have to decide if that is easier or harder than using ERLB in your situation.

AaronH replied on Sunday, April 04, 2010

Conceptually, how do you see a MobileList being created on the server?  It doesn't contain any DP methods.  Do you envision a list, such as an ERLB or BLB containing a static GetXXX method, whose return type is MobileList?

ajj3085 replied on Monday, April 05, 2010

I'd think you'd use a CommandBase subclass to execute a command and get the mobile list back.

RockfordLhotka replied on Monday, April 05, 2010

It is even easier than that.

The data portal works with any serializable types. You really don't need the 6 base classes from CSLA to use the data portal - though on Silverlight you do need to remember that "serializable" means that the type implements IMobileObject.

If you look at your typically business class, you'll probably notice that you rarely override DataPortal_Fetch(). Instead, you almost always just implement your own overload. In CSLA 4 there is no virtual DataPortal_Fetch(), because it has really become an inconvenience more than a help.

By extension then, you can infer that any class can implement DataPortal_Fetch() methods and the rest of the DP_XYZ methods too. And the data portal will talk to them just fine.

So all you need is something like this:

[Serializable]
public class MyList : Csla.Core.MobileList<MyItem>
{
#if !SILVERLIGHT
  private void DataPortal_Create()
  {
    ValidationRules.CheckRules();
  }

  private void DataPortal_Fetch()
  {
    // load list here
  }
#endif
}

You'll need a factory method too, along with whatever code is required to get the list to work the way you want. But the data portal will interact with this type just fine.

AaronH replied on Monday, April 05, 2010

Beautiful, thanks!

AaronH replied on Monday, April 05, 2010

I don't think I have my head around this like I thought I did.  Basically, I need the SL client to bring me back a list of EditableRoots.  From a SL client, typically this is done via a static call ObjectList.GetObjectList(id, handler); 

With the MobileList, this construct is not exposed (The MobileList doesn't present me with any async callback methods).  So it seems that I would need to produce the plumbing that would cause teh MobileList to go back to the server, load itself up with objects, and return to the SL client.

Is there any literature on the MobileList?  A previous blog post, video segment, chapter in a book?

I think I'm missing the point as to how or why you would leverage it.

ajj3085 replied on Monday, April 05, 2010

I'm not sure I understand what ObjectList.GetObjectList refers to.  Is this something you're finding in Csla, or something else?

Rocky's suggetion was to create your own static method..  MyMobileList.GetList() which in turn calls the async dataportal fetch method.  Then you implement a DataPortal fetch overload with the same parameters you used to call Fetch (minus any callback of course).

Any object which supports the IMobileObject can be called through the dataportal in that matter.

RockfordLhotka replied on Monday, April 05, 2010

Right, the base classes (BusinessBase, BusinessListBase, etc) provide absolutely 0 (zero) support for create/fetch operations beyond the (typically unused) virtual DataPortal_Fetch() method.

If "GetObjectList" is a factory method, then that's your code, not framework code. And you'd implement a factory in a MobileList exactly as you would in a BusinessListBase.

There are several base classes that implement IMobileObject - all of which are designed to be as light-weight as possible over the base .NET concepts:

These are all in Csla.Core and you should be able to infer what they are wrapping by their name.

There's also ExtendedBindingList<T>, which is the immediate base class for BLB and ERLB. And ReadOnlyBindingList<T> which is the immediate base class for ROLB.

In .NET you can use the data portal to directly retrieve a List<T>. In SL you need to use MobileList<T>, but it is the same thing - just with support for MobileFormatter.

AaronH replied on Monday, April 05, 2010

Thanks Andy.  I was using ObjectList as an example.  So:

public class ObjectList : MobileList<SomeEditableRoot>

So I get that, expose a static method (GetObjectList).  So then what?

It doesn't expose GetObjectList(id, handler) that takes a callback handler as an argument as the other CSLA classes do.  So basically, I would need to provide my own plumbing to have the MobileList call back to the server, have the server load the MobileList, and send it back.  No? 

Am I making sense?  If not, try the following.  Create two .NET CSLA classes: one that derives EntityRootListBase and one that derives from MobileList.  Give each one the same static method "GetXYZ" that returns an instance of itself. 

Now, in your SL project, link those two classes, and call each one.  You'll notice in the ERLB.GetXYZ() method, one of the arguments is a callback handler that is invoked when the DP call is complete.  You'll also notice that the ML.GetXYZ() method does not provide a callback handler as an argument.

So how am I to tell the ML.GetXYZ() method that it is supposed to make a call to the DP?

Hopefully I'm making sense here?

 

RockfordLhotka replied on Monday, April 05, 2010

Aaron, you wrote those GetXYZ() methods. They are your code, not CSLA code.

If you write your GetXYZ() as a synchronous method it will only work on .NET - that's true for ERLB, BLB or any other type.

If you write your GetXYZ() as an async method (with a callback parameter) it will work on SL and .NET. That's true for any type as well.

AaronH replied on Monday, April 05, 2010

Ohhhh, right.  This back and forth between CSLA SL and WCF RIA is killing me.  My apologies, I was thinking that a proxy was somehow being generated for me, and completely forgot that I've been creating my own SL implementation for the static methods.  It was a long weekend...

Copyright (c) Marimer LLC