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?
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.
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.
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
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
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
Copyright (c) Marimer LLC