Same Business Objects for both Asynchronous and Synchronous code

Same Business Objects for both Asynchronous and Synchronous code

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


RobKraft posted on Thursday, November 05, 2009

Our current CSLA application has a web UI and the business objects are also used by 3rd party developers to create their own interfaces. We are now converting our web UI to Silverlight and need to change our existing business objects to support the asynchronous nature of Silverlight. One challenge is that setting properties in many of our business objects could lead to database calls, but we don't want them to be asynchronous when used by batch .Net programs. We are looking for ideas that would allow a single business object to support both silverlight and batch clients with the same business logic.

Here is an example scenario that is problematic for our batch programs

obj.Category = value1; //This makes an asynchronous call to the database
obj.Problem = value2; //This makes an asynchronous call to the database to insure the problem value is valid for the given category
obj.Save();

In a batch program, the validation for Problem may not be complete before save gets called if we make some code within the setter for Problem asynchronous (which we need to do to support Silverlight). This is not a problem for our Silverlight UI because Save is not enabled until IsBusy = false;

One solution we are considering is to use have one Silverlight partial class that is Async, and a nonSilverlight partial class that is not. But we have thousands of these cases and a lot of them are very complicated, so we fear that we will be maintaining a lot of business logic twice.
Another solution we are considering is to force the property setters to behave synchronously by having code in the setter sit in a while loop and wait until the response has come back.

We don't like either of those solutions, and are wondering if anyone else has a similar situation and an elegant solution they would like to share.

Thanks in advance!

RockfordLhotka replied on Thursday, November 05, 2009

I'd just leave the rules as async - leverage multi-threading, etc. Just don't let the Save() call run until the rules complete:

      var obj = DataPortal.Create<Test>();
      Console.WriteLine("IsValid {0}", obj.IsValid);

      obj.Data = "abc";
      Console.WriteLine("Prop set");

      AutoResetEvent wait = new AutoResetEvent(false);
      obj.BusyChanged += (o, e) =>
        {
          if (!obj.IsBusy)
            wait.Set();
        };

      Console.WriteLine("Ready to save");
      wait.WaitOne();
      Console.WriteLine("About to save");
      Console.WriteLine("IsValid {0}", obj.IsValid);
      obj = obj.Save();
      Console.WriteLine("Saved");
      Console.ReadLine();

RobKraft replied on Thursday, November 05, 2009

I appreciate the swift reply but I don't think it quite addresses the problem we face. I can't think of a simplified example but we have lots of cases where setting properties will cause Async database calls (not just for validation, but also for calculations and population of other properties). We need to make sure that a second property is not set until the set of the first property is complete. We also don't want our 3rd party UI developers to need to account for this and modify all their existing code.

I think we can add an AutoResetEvent inside each property set of our business objects and the app should function correctly for Silverlight and batch/desktop programs (if not quickly); but then I think it may be a bottleneck for traditional ASP.Net apps because the AutoResetEvent will cause every user to wait on each user.

Perhaps there is no elegant way to support all 3 approaches in one business object - unless we add a switch to identify the type of environment the app is running in and thus whether or not to use Waits or Async.

JonnyBee replied on Friday, November 06, 2009

Hi Rob,

Yes, you have some challenges moving from a web app to SL. Just remember that everything on the serverside must be syncronous calls - you shold not start async operations in the serverside processes.

And the nature of async validation rules is:

So, following your example:
obj.Category = value1; //async call to DB
obj.Problem = value2;  //asyn call to DB, Category is a dependent property and value is copied to propertybag.

// you could potentially change obj.Problem again a starte a new async rule

// BUT: You must make sure that it is not valid to call Save until all rules have been processed - se other post on the forum for this.
obj.Save();


This forum thread has a bit more info on moving to SL: http://forums.lhotka.net/forums/thread/33755.aspx

Peran replied on Monday, November 16, 2009

Hi Rocky,

In this thread:
 
http://forums.lhotka.net/forums/permalink/32719/32727/ShowThread.aspx#32727

you provide the reason why it is not a good idea to enable setting of properties on the Target during an async validation rule.

Do you think it could be technically ok to have the concept of AsyncValidationRuleContext.OutArgs.PropertyValues to pass new values back to the validation subsystem and have the validation subsystem set the new property values of the Target on the main thread.


Cheers

Peran


Copyright (c) Marimer LLC