How to access Grandparent properties from the business rule of the grandchild

How to access Grandparent properties from the business rule of the grandchild

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


mtavares posted on Friday, March 11, 2011

I'm trying to write a business rule in a grandchild object that needs to check a property in the grandparent.  My hierarchy for the parent child relationship is Editable root --> EditableChild list --> Editable Child

The root has a date property in it that I want to check whether it has a value or not. If it has a value, then I want the rule to validate as an error, otherwise validate as a warning.

So I have 2 questions from this:

1. How can I access the granparent property from within the business rule class of the grandchild

2. How can I put a dependency rule on the grandparent property so that if the date changes the grandchild's property rules will run?

Here is what I tried for question #1:

 Private Class ObjectiveRequired
 Inherits Csla.Rules.BusinessRule

 Private descriptionProperty As IPropertyInfo

 Public Sub New(ByVal primaryProperty As IPropertyInfo, ByVal descProperty As IPropertyInfo)
  MyBase.New(primaryProperty)
  descriptionProperty = descProperty
  InputProperties = New List(Of IPropertyInfo) From {primaryProperty, descriptionProperty}
 End Sub

 Protected Overrides Sub Execute(ByVal context As RuleContext)
  Dim objectives As SgpObjectiveCollection = CType(context.InputPropertyValues(PrimaryProperty), SgpObjectiveCollection)
  Dim desc As String = CType(context.InputPropertyValues(descriptionProperty), String)
  Dim target As SgpPriority = CType(context.Target, SgpPriority)
  Dim parentCollection As SgpPriorityCollection = target.Parent
  If parentCollection IsNot Nothing Then
   Dim grandparent As SgpReport = parentCollection.Parent
   If grandparent IsNot Nothing Then
    If objectives.Count = 0 Then
     If CType(ReadProperty(grandparent, SgpReport.DateSubmittedProperty), SmartDate).IsEmpty Then
      context.AddWarningResult(String.Format("Objectives required for priority: {0}", desc))
     Else
      context.AddErrorResult(String.Format("Objectives required for priority: {0}", desc))
     End If
    End If
   End If
  End If
 End Sub

End Class

The problem with this is that the parent property on the target is always null.  And I really don't even know how to tackle #2.

I thought about possibly putting the rule in the grandparent, but I want the rule to run and generate an error for each grandchild object separately, so i'm not sure how to accomplish that from the grandparent.

Any help would be greatly appreciated.

Thanks.

Charleh replied on Friday, March 11, 2011

The parent property on the target should not be NULL - it should contain the business object or list object that is the direct parent of the target object

I have a few rules which need to go back to the parent list to check other objects in the list and they are working - are you running winforms/wfp or silverlight? Are these rules being executed server-side in a silverlight app?

Can you post the relationship and types of your objects?

As for #2, you can simply add a method to the grandchild object and call it from within PropertyChanged() on the grandparent - in that method just call BusinessRules.CheckRules(property) to check the properties that may have been affected

mtavares replied on Monday, March 14, 2011

Hi Charleh,

Thanks for responding.  On #1, I think I figured out my issue.  The target was only Null when the rule was being executed at the point of object being fetched, before it is added as a child to the collection, which is no big deal.  Where my problem was, was that I had forgotten to handle the Child_Changed events on my parent and grandparent and so the rules were never being re-validated.  Once I added that event handler the rule was executed and I had the proper parent and grandparent objects in my rule.

And your suggestion for #2 worked like a charm, thanks.

Munish Sehgal replied on Sunday, April 10, 2011

Hi friends, I'm facing the same problem..null parent reference in business rule. but I am unable to understand your solution of revalidating by parent. Please suggest me the answer...

Thanks!

mtavares replied on Monday, April 11, 2011

So as was suggested I just handled both the ChildChanged and the PropertyChanged events on the grandparent, and within them validated the child collection, and within the child objects of the collection validated the grandchild collection:

    Private Sub GrandParent_ChildChanged(ByVal sender As Object, ByVal e As Csla.Core.ChildChangedEventArgs) Handles Me.ChildChanged
        If TypeOf e.ChildObject Is ChildCollection OrElse TypeOf e.ChildObject Is Child OrElse TypeOf e.ChildObject Is GrandChildCollection OrElse TypeOf e.ChildObject Is GrandChild Then
            BusinessRules.CheckRules(ChildProperty)
            Child.ValidateCollection(True)
        End If
    End Sub


    Private Sub GrandParent_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles Me.PropertyChanged
        If e.PropertyName = "DateSubmitted" Then
            BusinessRules.CheckRules(ChildProperty)
            Child.ValidateCollection(True)
        End If
    End Sub
   

This sub is in the child collection:

    
    Public Overloads Sub ValidateCollection(ByVal IncludeChildren As Boolean)
        For Each item As C In Me
            item.ValidateObject(IncludeChildren)
        Next
    End Sub

And there is a ValidateObject function in the child that calls CheckRules, and then calls another validatecollection sub on the GrandChildCollection which in turn calls a validateObject function on each grandchild that again calls BusinessRules.CheckRules.

Hope this helps.

Munish Sehgal replied on Friday, April 15, 2011

Thanks Mtavares, I'll try it.

Copyright (c) Marimer LLC