Validation Rules need Lazy Loaded property

Validation Rules need Lazy Loaded property

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


nj609eagle posted on Tuesday, March 02, 2010

I have a person object that has a few rules that depend on a lzy loaded object of MembershipRecords.  The membership records was set to lazy load because they are not always needed across other applications and it became very large and slow to retireve. When the person object was serilized to disk is was 32kb, when the person object with the membership loaded was serilized, it was 1,048kb.

I have a custom valiation rule in the person object that needs to check a value in the membership Records property child object.  my rule has the following signature:

Private Shared Function SMSMailPrefValidation(Of T As Person)(ByVal target As T, ByVal e As Csla.Validation.RuleArgs) As Boolean

Then within the rule a line to get teh membership records object.

Dim _MemberRecords As Membership.MemberRecordList = target.GetProperty(MemberRecordsProperty)


the Membership records property is coded as such:

Public ReadOnly Property MemberRecords() As Membership.MemberRecordList
 Get
         If Not FieldManager.FieldExists(MemberRecordsProperty) Then
                    LoadProperty(Of Membership.MemberRecordList)(MemberRecordsProperty, Membership.MemberRecordList.GetMemberRecordByPersonID(PersonID:=Me.PersonID))
                End If
                Return GetProperty(Of Membership.MemberRecordList)(MemberRecordsProperty)
 End Get
End Property

But the fieldmanager.FieldExists is always true and does not load the object.
What do I need to change?

 

 

 

RockfordLhotka replied on Tuesday, March 02, 2010

Are you using the current version of CSLA? In some earlier versions I think there was a bug that caused FieldExists to erroneously return true.

But the other primary cause of this issue is accidentally "touching" the property. Data binding will touch it, and you could have other code that touches it. Anything that reads the property value will, of course, trigger your code and initialize the field - to null if nothing else.

ajj3085 replied on Tuesday, March 02, 2010

Are you sure you don't have code that's triggering the lazy load?  If you bind it, it may load, possibly even if you don't display it.  I'd put a breakpoint anywhere you do a LoadProperty for the collection in question.

nj609eagle replied on Tuesday, March 02, 2010

I'm using 3.8.1.

I removed the dim _MemberRecords line and changed it to target.MemberRecords.  this seems to have the effect I was hoping for.

Unfortunately I notived that i'm calling ValidationRules.CheckRules() at the bottom of the fetch, so the lazy load is a little pointless i think since now the whole object is getting returned all the time

 

JoeFallon1 replied on Wednesday, March 03, 2010

I think the trick is to make your rule a little smarter.

If the MemberRecords property is null then your rule should just return True. (Because in the current use case the property was not already loaded so it must not be needed.)

Only when there is an already loaded property should you attempt to validate the email. You should not be loading the lazy loaded object when it is not needed. Also, this will solve your issue with calling ValidationRules.CheckRules - it won't load the property just because you called a rule.

Joe

 

StefanCop replied on Friday, September 23, 2011

How would you do this? I tried (using CSLA 4.1)  both:

context.InputPropertyValues[PrimaryProperty] ¨

ReadProperty(context.Target, PrimaryProperty)

but both threw an Exception (from BusinessBase ReadProperty which checks for LayLoad and FieldExists).

What I would like is to have a FieldExists available in a BusinessRule.  Is there a way to check for field exists?

Steve

 

 

 

 

 

 

JonnyBee replied on Friday, September 23, 2011

Hi, In these cases I create the BusinessRule as an inner class inside the BO. This way I will get access to the inner properties/field of the BO, like FieldManager and can check if the field fieldExists.I would consider these rules as specialized rules for just this BO. Use snippet cslarule to create the inner rule. Semantical code to be placed inside the BO: private class InnerRule : Csla.Rules.BusinessRule { public InnerRule(IPropertyInfo primaryProperty) : base(primaryProperty) { } protected override void Execute(RuleContext context) { var myRoot = (Root)context.Target; var fm = myRoot.FieldManager; if (fm.FieldExists(PrimaryProperty)) { // do the check here var value = (objectType)myRoot.GetProperty(PrimaryProperty); } } }

Copyright (c) Marimer LLC