Slow Fetch() when business rules are implemented.

Slow Fetch() when business rules are implemented.

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


gajit posted on Wednesday, March 21, 2012

Hi gents,

Wonder if someone can put me back on the correct path...

It's taking an eon to perform a fetch on a single row because I have some properties that when changed, trigger other property changed events...

I'm pretty certain I'm doing it wrong... but I need a quick shove in the right direction...

I perform a fetch like so:

           Using data = New Csla.Data.SafeDataReader(dal.Fetch(_customerno))
                data.Read()

                Using BypassPropertyChecks

                    CustomerNo = data.GetString(data.GetOrdinal("CUSTOMERNO"))
                    MasterCustomerNo = data.GetString(data.GetOrdinal("MASTERCUSTOMERNO"))
                    Owner = data.GetString(data.GetOrdinal("OWNER"))
                    CompanyNo = data.GetString(data.GetOrdinal("COMPANYNO"))
                    Company = data.GetString(data.GetOrdinal("COMPANY"))
                    Address1 = data.GetString(data.GetOrdinal("ADDRESS1"))

What's killing the load time, is THIS type of property stub:

    Public Shared ReadOnly StateProperty As PropertyInfo(Of String) = RegisterProperty(Of String)(Function(c) c.State)
    <Display(Name:="State")> _
    Public Property State() As String
        Get
            Return GetProperty(StateProperty)
        End Get
        Set(value As String)
            SetProperty(StateProperty, value)
            PropertyHasChanged(CountryProperty)
            PropertyHasChanged(BranchProperty)
        End Set
    End Property

I basically have an (execute) command that is fired whenever the user changes the state, country or branch properties of my BO. So to make matters even worse, I have two propertyhaschanged() methods on the other two properties.

Should I be using a different method? Maybe BusinessRules.CheckRules?

As soon as a user changes any of the 3 values in the UI, I need to do the check and update the UI accordingly.

My validation rules look like:

            .AddRule(New CheckBranchIsValid() With {.PrimaryProperty = StateProperty})
            .AddRule(New CheckBranchIsValid() With {.PrimaryProperty = BranchProperty})
            .AddRule(New CheckBranchIsValid() With {.PrimaryProperty = CountryProperty})

and the execute looks like:

    Private Class CheckBranchIsValid
        Inherits Csla.Rules.BusinessRule
        Protected Overrides Sub Execute(context As Csla.Rules.RuleContext)

            Dim target = DirectCast(context.Target, CustomerEdit)

            If Not PrimaryProperty.Equals(BranchProperty) Then AffectedProperties.Add(BranchProperty)
            If Not PrimaryProperty.Equals(StateProperty) Then AffectedProperties.Add(StateProperty)
            If Not PrimaryProperty.Equals(CountryProperty) Then AffectedProperties.Add(CountryProperty)

            If Not CustomerEdit.BranchIsValid(target.Phone, target.Branch, target.State, target.Country) Then
                context.AddErrorResult("Branch, Country or State is invalid")
            End If

        End Sub
    End Class

I know I'm doing "something" wrong, just now sure what.

Any help would be appreciated.

Thanks,

Graham

 

 

 

 

 

 

 

 

 

gajit replied on Wednesday, March 21, 2012

Having peeked at the CSLA books again, I *think* I've fixed it. There's still some I/O going on when I fetch the data (which I don;t quite understand why - because I'm in a "Using BypassPropertyChecks"

But I removed all of the PropertyHasChanged method calls and removed the Affectedproperties code in my execute method.

I created dependency rules on the properties in question as such:

            .AddRule(New Csla.Rules.CommonRules.Dependency(BranchProperty, StateProperty))
            .AddRule(New Csla.Rules.CommonRules.Dependency(BranchProperty, CountryProperty))

            .AddRule(New Csla.Rules.CommonRules.Dependency(StateProperty, BranchProperty))
            .AddRule(New Csla.Rules.CommonRules.Dependency(StateProperty, CountryProperty))

            .AddRule(New Csla.Rules.CommonRules.Dependency(CountryProperty, BranchProperty))
            .AddRule(New Csla.Rules.CommonRules.Dependency(CountryProperty, StateProperty))

            .AddRule(New CheckBranchIsValid() With {.PrimaryProperty = StateProperty})
            .AddRule(New CheckBranchIsValid() With {.PrimaryProperty = BranchProperty})
            .AddRule(New CheckBranchIsValid() With {.PrimaryProperty = CountryProperty})

 

is this the correct strategy?

 

JonnyBee replied on Wednesday, March 21, 2012

Just out of curiosity - how many times do you want the same and probably expensive rule to execute?

My preference is to use InputProperties as dependency to have one and the same rule run just once for one primary property when either primary property or one of the InputProperties is changed.

RockfordLhotka replied on Wednesday, March 21, 2012

As a general rule you should have exactly one line in a property setter: the call to SetProperty.

If you want other properties to change, or their rules to run, when the setter runs you should use rules to do that work. That way the processing will be supressed by BypassPropertyChecks or other rule supression techniques.

gajit replied on Wednesday, March 21, 2012

Thanks Rocky.

Yep, I think my reworking falls under that technique.

Graham

 

Copyright (c) Marimer LLC