Design question... How to identify IsValid==false in a large tree of BOs

Design question... How to identify IsValid==false in a large tree of BOs

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


ixman posted on Monday, April 14, 2008

Hi,

I have a quite large tree of business objects. Sometimes when I call Save() on the root object, I get the IsValid == false because some object in the tree is invalid or maybe more. I want to know if there is a pattern or guideline on how to quickly find the object that is invalid other than scrolling down the tree looking for the IsValid in the debug visualizer.

Thanks,

George B

skagen00 replied on Monday, April 14, 2008

You know, I very much see where you're coming from with your post as I've had to really scour the object graph in debug to figure out exactly why something wasn't valid. I don't know of any inherent way to do so, but it would probably not be unreasonable to provide this sort of support in your company's business base if you find this scenario happening very often where you're spending lots of time hunting for invalid objects.

I'm sure you could likely use reflection to hop through the object graph when the root's IsValid is false.

Obviously multiple objects could potentially be invalid too.

sergeyb replied on Monday, April 14, 2008

If anyone is interested, I wrote a helper class that can examine an object graph and output combine error message.  Feel free to modify it and adapt it to your needs.

 

 

Imports System.ComponentModel

 

Public Class CSLABusinessObjectErrorTextExaminer

    Private Sub New()

    End Sub

    ''' <summary>

    ''' Get text for errors if object is invalid

    ''' </summary>

    ''' <returns>Error text for invalid object</returns>

    ''' <remarks></remarks>

    Public Shared Function GetErrorInformation(ByVal target As Object) As String

        Dim inspectedObjects As New Collections.Generic.List(Of String)

        Return GetErrorInformation(target, inspectedObjects)

    End Function

 

    ''' <summary>

    ''' Get text for errors for one object based on IDataErrorInfo interface

    ''' </summary>

    ''' <param name="target">Object to get error text for</param>

    ''' <param name="inspectedObjects">List of hash codes of objects that are inspected.

    ''' This is necessary to avoid infinite recursion.

    ''' </param>

    ''' <returns>Text for errors for one object based on IDataErrorInfo interface</returns>

    ''' <remarks></remarks>

    Private Shared Function GetErrorInformation(ByVal target As Object, ByVal inspectedObjects As Collections.Generic.List(Of String)) As String

        Dim returnValue As New Text.StringBuilder()

        Dim targetID As String = String.Empty

        If target IsNot Nothing Then

            targetID = target.GetType.ToString & ":" & target.GetHashCode().ToString

        End If

        If target IsNot Nothing AndAlso Not inspectedObjects.Contains(targetID) Then

            inspectedObjects.Add(targetID)

            If TypeOf target Is IBindingList Then

                ' check error messages for each row in the list

                For oneItem As Integer = 0 To CType(target, IBindingList).Count - 1

                    If TypeOf CType(target, IBindingList)(oneItem) Is Csla.Core.BusinessBase Then

                        Dim itemError As String = GetErrorInformation(CType(target, IBindingList)(oneItem), inspectedObjects)

                        ' if we do not have this message already, add it

                        If itemError.Length > 0 AndAlso Not returnValue.ToString.Contains(itemError) Then

                            returnValue.Append(itemError)

                            returnValue.Append(Environment.NewLine)

                        End If

                    End If

                Next

            Else

                If TypeOf target Is Csla.Core.BusinessBase Then

                    ' run through broken rules collection for this object

                    For Each oneBrokenRule As Csla.Validation.BrokenRule In CType(target, Csla.Core.BusinessBase).BrokenRulesCollection

                        ' if we do not have this message already, add it

                        If Not returnValue.ToString.Contains(oneBrokenRule.Description) Then

                            returnValue.Append(oneBrokenRule.Description)

                            returnValue.Append(Environment.NewLine)

                        End If

                    Next

                    ' get list of properties for this object

                    Dim properties() As System.Reflection.PropertyInfo = target.GetType.GetProperties()

                    For Each oneProperty As System.Reflection.PropertyInfo In properties

                        ' get object that sits on this property

                        If Not oneProperty.PropertyType.IsPrimitive AndAlso oneProperty.GetIndexParameters().Length = 0 Then

                            Dim propTarget As Object = oneProperty.GetValue(target, Nothing)

                            ' call this procedure resursively to get error for property based object

                            Dim propErrorText As String = GetErrorInformation(propTarget, inspectedObjects)

                            ' if we do not have this message already, add it

                            If propErrorText.Length > 0 AndAlso Not returnValue.ToString.Contains(propErrorText) Then

                                returnValue.Append(propErrorText)

                                returnValue.Append(Environment.NewLine)

                            End If

                        End If

                    Next

                End If

            End If

        End If

        ' strip out duplicate carriage returns before returning the value.

        Return returnValue.ToString.Replace(Environment.NewLine & Environment.NewLine, Environment.NewLine)

    End Function

End Class

 

 

 

Sergey Barskiy

Senior Consultant

office: 678.405.0687 | mobile: 404.388.1899

cid:_2_0648EA840648E85C001BBCB886257279
Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: skagen00 [mailto:cslanet@lhotka.net]
Sent: Monday, April 14, 2008 8:56 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] Design question... How to identify IsValid==false in a large tree of BOs

 

You know, I very much see where you're coming from with your post as I've had to really scour the object graph in debug to figure out exactly why something wasn't valid. I don't know of any inherent way to do so, but it would probably not be unreasonable to provide this sort of support in your company's business base if you find this scenario happening very often where you're spending lots of time hunting for invalid objects.

I'm sure you could likely use reflection to hop through the object graph when the root's IsValid is false.

Obviously multiple objects could potentially be invalid too.



ixman replied on Monday, April 14, 2008

Hi,

Thanks for your ideas... I'll check the solutions and I'll post my results...

Regards,

George B

Copyright (c) Marimer LLC