Async Business Rules That Change Other Collection Properties

Async Business Rules That Change Other Collection Properties

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


Savij posted on Tuesday, August 10, 2010

Hello,

I am working on a  problem that I will try to simplify to explain. I am using Csla 4.0 and a Silverlight 4 project. Lets say I have an object called 'Foo'. Foo has a EditableCollection<Bar> as a child property the property is called BarCollection. Bar has 2 properties called PropertyA and PropertyB.

I want to add an Async rule on PropertyA so that if PropertyA changes, the rule will need to update other instances of Bar in the Parent Collection. What I mean by this, is that if Foo.BarCollection[0].PropertyA changes, then I need to have the rule update Foo.BarCollection[1].PropertyB (and possibly all other PropertyB's in the collection).

Any help is greatly appreciated!!

-Jeff

RockfordLhotka replied on Tuesday, August 10, 2010

I assume your rule goes to the server and retrieves a value (or some values) and then needs to use those values to update the object graph?

You can do this, but not with out values.

To do this, your rule needs to indicate that it wants the Target property to be available even though the rule is async by setting ProvideTargetWhenAsync=true in the constructor.

You can then use the Target property to gain access to your business object (and thus the entire object graph).

Just remember that you can only use the Target property when your rule is running on the UI thread. If you access the Target property from a background thread you'll cause problems - hopefully the least of which is that you'll get cross-threading exceptions.

Savij replied on Tuesday, August 10, 2010

Rocky,

Yes, you are correct I am dealing with a Csla BusinessBase that goes to the server. I guess I really didnt explain the rest of the issue in the posting. Your answer did provide me with the missing Target which was a good thing. The problem I still face is that I have a dynamic validation class that sometimes calls Async validations and sometimes it calls sync validations. The method looks like this:

protected override void Execute(Csla.Rules.RuleContext context)
{
Property property = (Property) context.Target;
var bw = new System.ComponentModel.BackgroundWorker();
bw.DoWork += (o, e) =>
{
foreach (ValidatorInfo validatorInfo in property.ValidatorList)
{
   string message = string.Empty;
   // this line may or may not require a trip to the server, and it calls a ReadOnlyBase to make the trip if needed.
   if (!validatorInfo.Validate(property.Value, property.LabelText, property.Task.TaskItems, ref message))
   {
      context.AddErrorResult(message);
   }
}
};

The problem is that inside validatorInfo.Validate calls out to an Async ReadOnlyBase. This code is used to help validate the dynamic property. If the code needs to go to the server, how can I block the thread (background thread) and wait for the async fetch of the ReadOnlyBase? Right now, it's returning before the async ReadOnlyBase is finished.

This is a dynamic system that creates views and rules from a database on the fly. It's not a normal situation, but I have tried to simplify what I am doing best I can to convey the idea.

Any ideas how can I get this to work?

Thanks,

-Jeff

RockfordLhotka replied on Tuesday, August 10, 2010

You should really try to come up with a design that relies on completion events - no blocking. I know that's not always easy - but that is really what you should do.

If you are absolutely sure you are on a background thread (remember that completion events in SL are on the UI thread - so your code is almost never on a background thread in SL!!!), then you can block the thread using synchronization primitives from System.Threading.

You'll know if you get it wrong, because you'll completely lock up the browser Big Smile

Copyright (c) Marimer LLC