CSLA .NET

Vibrant discussion about CSLA .NET and using the framework to build great business applications.

Forum has moved

New location: CSLA .NET forum


CSLA .NET Resources:
  • CSLA .NET forum
  • CSLA .NET home page
  • Calculating Rules for two Dependend Properties

    rated by 0 users
    Answered (Verified) This post has 1 verified answer | 3 Replies | 1 Follower

    Top 500 Contributor
    21 Posts
    ThiloS posted on Thu, Apr 25 2013 8:21 AM

    CSLA Version 4.1

    Hello !

    I have two Properties: one called DeliveryWeek (LieferKW) and one called DeliveryDate (Liefertermin).
    Further i have two Rules which calculate a DeliveryDate (Friday of Week) from DeliveryWeek
    and one Rule that calculate a DeliveryWeek vom DeliveryDate.
    The User must can change both (vice versa) in the WPF UI and the other Field must be updated.
    The Problem is, that when the user enter a new DeliveryDate the CalculateLieferterminRule runs first
    and reset the DeliveryDate.
    What is the right Way to setup the Rules ?

    My Code:
            protected override void AddBusinessRules()
            {
                base.AddBusinessRules();

                //Some Other Rules for Required Fields
               
                //BusinessRules.AddRule(new Csla.Rules.CommonRules.Dependency(LieferKWProperty, LieferterminProperty));
                //BusinessRules.AddRule(new Csla.Rules.CommonRules.Dependency(LieferterminProperty, LieferKWProperty));
                BusinessRules.AddRule(new CalculateLieferterminRule(LieferterminProperty, LieferKWProperty){Priority = 1});
                BusinessRules.AddRule(new CalculateLieferKWRule(LieferKWProperty, LieferterminProperty) { Priority = 1 });

            }
           
            private class CalculateLieferterminRule : BusinessRule
            {
                private IPropertyInfo LieferKWProperty;
               
                public CalculateLieferterminRule(IPropertyInfo primaryProperty, IPropertyInfo lieferKWProperty) : base(primaryProperty)
                {
                    if (InputProperties == null)
                    {
                        InputProperties = new List<IPropertyInfo>() {primaryProperty, lieferKWProperty};
                    }

                    PrimaryProperty = primaryProperty;
                    LieferKWProperty = lieferKWProperty;
                    AffectedProperties.Add(PrimaryProperty);

                }

                protected override void Execute(RuleContext context)
                {
                    var lieferKw = Convert.ToInt32(context.InputPropertyValues[LieferKWProperty]);
                    DateTime? liefertermin = DateTimeExtension.GetLastBusinessDateOfWeek(lieferKw);

                    context.AddOutValue(PrimaryProperty, liefertermin);
                }

            }

            private class CalculateLieferKWRule : BusinessRule
            {
                private IPropertyInfo LieferterminProperty;
               
                public CalculateLieferKWRule(IPropertyInfo primaryProperty, IPropertyInfo lieferterminProperty) : base(primaryProperty)
                {
                    if (InputProperties == null)
                    {
                        InputProperties = new List<IPropertyInfo>() {primaryProperty, lieferterminProperty};
                    }

                    PrimaryProperty = primaryProperty;
                    LieferterminProperty = lieferterminProperty;
                    AffectedProperties.Add(PrimaryProperty);
                }

                protected override void Execute(RuleContext context)
                {
                    var liefertermin = Convert.ToDateTime(context.InputPropertyValues[LieferterminProperty]);
                    int lieferKW = DateTimeExtension.GetCalendarWeekWithYear(liefertermin);

                    context.AddOutValue(PrimaryProperty, lieferKW);
                }
            }

     

     

    Answered (Verified) Verified Answer

    Top 10 Contributor
    2,279 Posts
    Answered (Verified) JonnyBee replied on Thu, Apr 25 2013 11:18 AM
    Verified by ThiloS

    Hi,

    First. Remove the dependecy rules.  AffectedProperty creates a dependency.

    Then rewrite the rules to set the "AffectedProperty" -  ie: the CalculateLieferKWRule should have LieferTerminProperty as primary property and LieferKWProperty as Output property/AffectedProperty.

    The rule engine will for a given property run the rules

    • first where the Property is a PrimaryProperty in Priority Ascending order
    • then run rules for affected properties in random
      •  for each property run rules in Priority Ascending order

    So as your rules is defined now - when LieferterminProperty is changed the rules where LiferterminProperty is primary property will run first and that is the CalculateLieferteminRule. 

    Jonny Bekkum, Norway CslaContrib Coordinator

    All Replies

    Top 10 Contributor
    2,279 Posts
    Answered (Verified) JonnyBee replied on Thu, Apr 25 2013 11:18 AM
    Verified by ThiloS

    Hi,

    First. Remove the dependecy rules.  AffectedProperty creates a dependency.

    Then rewrite the rules to set the "AffectedProperty" -  ie: the CalculateLieferKWRule should have LieferTerminProperty as primary property and LieferKWProperty as Output property/AffectedProperty.

    The rule engine will for a given property run the rules

    • first where the Property is a PrimaryProperty in Priority Ascending order
    • then run rules for affected properties in random
      •  for each property run rules in Priority Ascending order

    So as your rules is defined now - when LieferterminProperty is changed the rules where LiferterminProperty is primary property will run first and that is the CalculateLieferteminRule. 

    Jonny Bekkum, Norway CslaContrib Coordinator

    Top 500 Contributor
    21 Posts
    ThiloS replied on Fri, Apr 26 2013 5:14 AM

    Hello Jonny,
    thank you for your quick answer, it works. I was some Kind of BlindSmile, Naturally must the Primary Property be the Property wich is the source for the calculating.

    But for me i have another question with Rules.

    What is the best 'CSLA Style' to implement such calculations and what is the effort to make it in Rules ?
    I mean, that i also can do this sort of calculation in the setter of the Property.
    In the RuleTutorial are a lot of Validation Rules, but not so many Calculation Rules.

    Top 10 Contributor
    2,279 Posts

    Hi Thilo,

    In general terms:

    • when you have "double" linked dependencies like you described here (Property A when changed sets property B and Property B when changed sets Property A), the calculation must occur in rules where the changed property is PrimaryProperty
    • When you have calculations (like sum or  subtract) my recommendation is to have the resulting property as PrimaryProperty (much like you would in an excel spreadsheet) and add all the properties required in the InputProperties collection (starting in CSLA 4.2 this is regarded as an implicit dependency too so that you do need to add separate dependency rules -  the rule will be called whenever one of the input properties is changed and AFTER the business rules for the changed rule has executed).

    Starting from CSLA 4.2 you can also tell the rule engine when NOT to run the rule:

    • CanRunInCheckRules when false means that the rule will not be executed when <bo>.CheckRules() is called.
      CanRunAsAffectedProperty when false means that this property rule will not run when this property is an affected property on another property rule.
    • CanRunOnServer when false means that this property rule will not run on the “logical” server side, by all practical means in Data Access Layer.
      So when CheckRules is called from Data Access do not execute this rule when set to false.

    You should also look at my blog posts:

    http://jonnybekkum.wordpress.com/2011/08/29/csla-4-2-rules-update/
    http://jonnybekkum.wordpress.com/2012/11/07/csla-4-5-ruleengine-update/

    Jonny Bekkum, Norway CslaContrib Coordinator

    Page 1 of 1 (4 items) | RSS

    Copyright (c) 2006-2014 Marimer LLC. All rights reserved.
    Email admin@lhotka.net for support.
    Powered by Community Server (Non-Commercial Edition), by Telligent Systems