BusinessRule AddOutValue method

BusinessRule AddOutValue method

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


RaulLozano posted on Wednesday, April 27, 2011

Hello.

Why is it that if I call the AddOutValue method on a business rule with the PropertyInfo argument set to a property that is *not* the PrimaryProperty or that was *not* added to the AffectedProperties collection the call fails?

Looking at the implementation of the AddOutValue you can see that is raises an error if the property is not part of the AffectedProperties collection.

public void AddOutValue(Csla.Core.IPropertyInfo property, object value)
{
    if (!Rule.AffectedProperties.Contains(property))
        throw new ArgumentOutOfRangeException(property.Name);

}

So my question is what is the reason for this restriction?

Thank you.

 

RockfordLhotka replied on Wednesday, April 27, 2011

You can (and must) add that property to the affected properties list yourself. For better or worse, the intent is to make you be explicit about the properties affected by your rule.

rxelizondo replied on Wednesday, April 27, 2011

 

Hi Rocky,

So I am guessing that behind the scenes the AddOutValue() method ends up triggering the rules for the property passed as its argument and so the CSLA forces the developer to add the property to the AffectedProperties collection so that the developer is not surprised the other rules are being triggered?

 So just for fun, I delete the following code:

    if (!Rule.AffectedProperties.Contains(property))

        throw new ArgumentOutOfRangeException(property.Name);

and everything should work just fine?

Thanks.

 

RockfordLhotka replied on Wednesday, April 27, 2011

I doubt that Rene. If the property isn't in the affected properties list, I don't think CSLA will update the property value or do other normal processing.

What you maybe could do, is if the property isn't in the affected properties list, you could automatically add it to the list.

JonnyBee replied on Thursday, April 28, 2011

Oh, no......

Remember - this rule instance is registered for ALL instances of this object type and the rule properties should NOT be changed in execution of a rule (wether sync or async rule is used).

AffectedProperties is also used for :

So - you may end up with AddOutValue changing the values of properties and the rules not being run and field value is out of sync with validation rules (ie not validated).

So as the codebase is now - it is not safe to use OutputValues that do not exist in AffectedProperties in async rules.

Quote from "Using Csla4-02-Objects":

"It is critical that you understand that instance properties or fields in a rule object can not be changed after the rule object has been created.

You must initialize instance properties and fields as the object is created, and never change them from that point forward.

This restriction exists because each rule object is shared by all instances of the business type with which the rule is associated. If you did change a property or field in a rule, you’d instantly affect all business objects using that rule, and the result would almost certainly be inconsistent behavior that would be difficult to identify, debug and fix. "

 

 

RockfordLhotka replied on Thursday, April 28, 2011

Thank you Jonny - my head is so deep in authentication right now I guess I totally missed this very obvious point!

You've saved us all a lot of heartache!

ajj3085 replied on Monday, October 17, 2011

Sorry for resurrecting an old thread, but I just found this while starting to work with Csla 4.1.

I thought there was a bug in Csla, so I replaced this:

context.AddOutValue(SecondaryProperty, value);

with this:

LoadProperty(context.Target, SecondaryProperty, value);

to work around it and things seem to work fine.  If this is in fact a problem, shouldn't LoadProperty also throw an exception?

Also, I don't quite understand the logic.  If you call AddOutValue, its pretty clear you're intending to modify a value.  Forcing a developer to list everything in AffectedProperties seems to be extra busy work.  Any reason AddOutValue can't do that for you?

JonnyBee replied on Tuesday, October 18, 2011

Hi Andy,

Remember the Dependency rule from Csla3.x? The equivalent in Csla 4.0/4.1 is AffectedProperties.

Meaning that the rule engine will rerun rules for AffectesProperties in a consistent way - no matter if AddOutValue was called or not. That is simply what the Dependency rules in Csla 4.x dows. This is important when you start to create asyncronous lookup rules that update fields in your BO.  Affected properties will be marked as Busy when the rule starts to execute and cannot be set for as long as the async rule is running.

LoadProperty is for "border" conditions where Affected Properties (and a rerun of rules) is NOT desired or for updating properties on other objects than RuleContext.Target.  You could for example create a recursive loop with two asyncronous rules that update each others fields and finally run into a StackOwerflow exception that would only be avoided by using LoadProperty.  (For Csla 4.2 this can be avoided by not allowing the async rule to be triggered as AffectedProperty).

Any rule instance should be considered a singelton and NO property must be changed after that instance is registered for a given BO type. Meaning that the single rule instance will be used for ALL instances of the given BO type and you cannot update AffectedProperties based on whatever is called by RuleContext.AddOutValue .

Another challenge with your code is - how to rerun rules for the properties that you update in LoadProperty - and especially in asyncronous lookup rules?

If you use AffectedProperties/AddOutValue it will work consistently in both sync and async rules without additional code.

ajj3085 replied on Tuesday, October 18, 2011

In my case there are no rules for the other properties.  They're not even public.  I finally realized what I needed to do to get it working, it just didn't work as easily as I expected. 

I guess its a small price to pay for the ability to easily make async rules.

Copyright (c) Marimer LLC