Hi Rocky
I ran into an interesting problem in 4.1 that I think needs your input. I have the following scenario:
2 properties: string CustomerName, and int? CustomerId
On my CustomerName property I have a business rule set up to set the CustomerId to null the CustomerName is set to an empty string.
On my CustomerId property I have a business rule set up to load some other proeprties when the CustomerId is set - and this is an asynch rule which makes a server call.
The problem is that my CustomerName rule lists CustomerId as an affected property (as it has to to be able to set it). But when the rule executes, even if it doesn't call context.AddOutValue for the CustomerId property, the rule associated with CustomerId gets fired anyway (and this is a problem because it causes the server call unnecessarily).
It would be really nice if there was some way of indicating that only affected properties that are actually set cause their rules to execute.
I did try using context.AddSuccessResult(true) to stop processing but this has no effect - and I can see in the code that it's already added all the AffectedProperties to a list of properties to execute the rules for.
On a side note, I did think that maybe a way to achieve this would be to not have the CustomerId property set in the AffectedProperties list. But then I get an exception when I try to call context.AddOutValue(CustomerIdProperty, null) as the AddOutValue method checks whether the property having a value set is an affected property.
One other possibility is to setup the AffectedProeprties collection in the Execute method - i.e. at the start of the method clear the AffectedProperties collection and then only add the properties that are actually affected.
Anyway I would be interested in your comments.
Craig
Hi Craig,
It would be really nice if there was some way of indicating that only affected properties that are actually set cause their rules to execute.
No, I don't think we should break the meaning of AffectedProperties. Rules should always run for AffectedProperties.
But, the case here may rather be: I'd like to call AddOutValue for properties that are not part of AffectedProperties (and thus - the rules will not be run).
You should however be aware that I have made some changes in BusinessRules since Csla 4.1 was release so that:
This may affect how your rules are executing and dependencies.
Hi Jonny
I'm not sure I understand your description of the changes you've made, but I certainly agree that it should be possible to add an output value from a rule for a property without having to make it an affected proeprty. That would certainly solve my problem, I think.
In the interim, I've had some success with not defining the AffectedProperties in the ctor of the rule, but setting them in the execution of the rule. I'm pretty sure there shouldn't be issues with this (but please advise if you think there are!!! )
Cheers...
Craig
Hi Craig,
You must remember that the instance of the Rule is registered (similar to a singelton) for ALL instances of the BO type.
So - your code must be thread safe and ALL properties should be immutable (not changed for each execution).
If you are inheriting from Csla.Rules.BusinessRule, you can call LoadProperty to change a property value without the property being an AffectedProperty.
Peran
Hi Jonny
Thanks for the advice. I did know that rules were shared amongst business objects - so yes, what I'm doing is technically wrong, though in my particular circumstance it doesn't matter as there's only ever a single instance (at a time) of the business object being validated.
It is a bit of a worry though that, without reading the documentation and warnings, that one can easily assume that there is a rule instance per business object instance.
I wonder if maybe it would be better to, in some way, prevent invalid modification to the state of the shared BusinessRule instance after construction. E.g. throw exceptions if used incorrectly.
Craig
I think even if you only have one BO at a time being validated you could run into problems. The first run could cause the second run for the new BO to return an incorrect result.
Unfortunately there's nothing you can do to signify that a class should be immutable.
Copyright (c) Marimer LLC