Using BrokenRule and BrokenRulesCollection in CSLA Command Object.

Using BrokenRule and BrokenRulesCollection in CSLA Command Object.

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


tarekahf posted on Tuesday, February 21, 2012

I am trying to use BrokenRulesCollection as a property of a Command Object, but I am unable to create a new instance of a BrokenRule and Add it to the collection.

In summary, inside the Command Object, I am calling other CSLA Objects to carry out some Database Updates for several Objects inside a Loop.

I want to capture all possible errors including Validation Errors, and return them in a collection object which can be accessed via the UI code.

I am thinking to use the BrokenRulesCollection, is this a good idea?

Or should I use List of String (Arrays) to capture the errors ...etc and return the resutls as a simple array ?

Why I cannot create BrokenRules objects ?

Tarek.

 

JonnyBee replied on Tuesday, February 21, 2012

In general terms - I would not use BrokenRule / BrokenRuleCollection for this purpose. These classes exist for a specific responsibility on BusinessRules.

1. Your other CSLA objects may have structure/tree of BrokenRules (not just on the root object).

2. All possible errors (Exceptions) may not map directly to a BrokenRules, f.ex Inner exceptions may hold essential data. Or how about DataPortalException that may or may not have a BusinessException (as inner exception).

I believe you should create your own structure for this purpose and send back to your client application.

tarekahf replied on Wednesday, February 22, 2012

Hi Jonny,

Yes, I agree with you. This is what I have done to report errors back to the UI:


    Public Shared Function RefreshDBFields(ByVal theUserCtrlInfoPack As UserCtrlInfoPack, ByVal DoGetCountOnly As Boolean) As RefreshDBFieldsCommand
        Dim result As RefreshDBFieldsCommand
        If Not AppSecurity.GetSingleton.IsUserAuthorized(AppSecurity.CodesApp.eHRMD, AppSecurity.CodesActions.RefreshDBFlds, AppSecurity.CodesDataTypes.SPMSForm, theUserCtrlInfoPack) Then
            Throw New System.Security.SecurityException( _
                String.Format( _
                    My.Resources.NotAuthErrorPrm2, _
                    theUserCtrlInfoPack.AuthUserID, _
                    AppSecurity.CodesActions.RefreshDBFlds.ToString, _
                    SPMSForm.GetSPMSFormInits.GetObjectName, "<all>"))
        End If
        result = DataPortal.Execute(Of RefreshDBFieldsCommand)(New RefreshDBFieldsCommand(theUserCtrlInfoPack, DoGetCountOnly))
        Return result
    End Function

    Public Class RefreshDBFieldsCommand
        Inherits CommandBase

        Private mRecordsToBeRefreshedCnt As Integer
        Private mRecordsRefreshedCnt As Integer
        Private mDoGetCountOnly As Boolean
        Private mRecordVersion As Integer
        Private mUserCtrlInfoPack As UserCtrlInfoPack
        Private mMessages As New List(Of String)
        Private mSuccess As Boolean

        Public ReadOnly Property RecordsToBeRefreshedCnt() As Integer
            Get
                Return mRecordsToBeRefreshedCnt
            End Get
        End Property

        Public ReadOnly Property RecordsRefreshedCnt() As Integer
            Get
                Return mRecordsRefreshedCnt
            End Get
        End Property

        Public ReadOnly Property Messages() As String()
            Get
                Return mMessages.ToArray()
            End Get
        End Property

        Public ReadOnly Property Success() As Boolean
            Get
                Return mSuccess
            End Get
        End Property

        Public Sub New(ByVal theUserCtrlInfoPack As UserCtrlInfoPack, ByVal DoGetCountOnly As Boolean)
            mUserCtrlInfoPack = theUserCtrlInfoPack
            mDoGetCountOnly = DoGetCountOnly
            mSuccess = True
        End Sub

        Protected Overrides Sub DataPortal_Execute()
            Dim theSPMSForm As SPMSForm = Nothing
            Dim theStaffID As String
            Dim theReviewFrom As String
            Dim theMsg As String
            Using cn As New SqlConnection(Database.SPMSFormDB)
                cn.Open()
                Using cm As SqlCommand = cn.CreateCommand
                    cm.CommandType = CommandType.StoredProcedure
                    cm.CommandText = "uspSPMSFormListGetRecVer"
                    cm.Parameters.AddWithValue("@RecVer", SPMSForm.GetSPMSFormInits.RecordVersion)
                    mRecordsToBeRefreshedCnt = 0
                    mRecordsRefreshedCnt = 0
                    Using da As New SqlDataAdapter(cm)
                        Using ds As New DataSet
                            da.Fill(ds)
                            mRecordsToBeRefreshedCnt = ds.Tables(0).Rows.Count
                            If Not mDoGetCountOnly Then
                                For Each theRow As DataRow In ds.Tables(0).Rows
                                    theStaffID = theRow.Item("StaffID")
                                    theReviewFrom = theRow.Item("ReviewFrom")
                                    mUserCtrlInfoPack.SetQueryUser(theStaffID)
                                    Try
                                        theSPMSForm = SPMSForm.GetSPMSForm(cn, mUserCtrlInfoPack, theReviewFrom)
                                        theSPMSForm.SetSubmitActionRefreshDBFlds()
                                        theSPMSForm.SaveForm()
                                    Catch ex As Csla.Validation.ValidationException
                                        mSuccess = False
                                        mMessages.AddRange(theSPMSForm.BrokenRulesCollection.ToArray())
                                    Catch ex As Exception
                                        mSuccess = False
                                        theMsg = _
                                            String.Format(My.Resources.ErrRefreshDBFlds, _
                                                        ex.Message, theSPMSForm.GetObjectName(), theSPMSForm.IDStr, _
                                                        mUserCtrlInfoPack.AuthUserID)
                                        mMessages.Add(theMsg)
                                    End Try
                                    mRecordsRefreshedCnt += 1
                                    theSPMSForm = Nothing
                                Next
                                If mSuccess Then
                                    theMsg = _
                                        String.Format( _
                                            My.Resources.RefreshDBFldsConf, _
                                            SPMSForm.GetSPMSFormInits.GetObjectName(), mRecordsRefreshedCnt.ToString, _
                                            mRecordsToBeRefreshedCnt.ToString)
                                    mMessages.Add(theMsg)
                                End If
                            End If
                        End Using
                    End Using
                End Using
            End Using

        End Sub
    End Class

I have yet to test the code above. By the way, this is related to the same post I did before (Progress Bar Implementation with Command Object):

http://forums.lhotka.net/forums/t/11176.aspx

Do you have any comment on this matter?

Side Questions: Is there an easy way to insert VB or C# code in this forum ?

Tarek.

JonnyBee replied on Wednesday, February 22, 2012

Not knowing how your business object structure is, ther may be some issues with: 

           mMessages.AddRange(theSPMSForm.BrokenRulesCollection.ToArray()) 

If theSPMSForm has child objects/lists with broken rules you need to use BusinessRules.GetAllBrokenRules (static method) to
get the broken rules from all nodes - the entire tree - and eventually merge into a list of broken rules.

The ProgressBar implementation is very similar (same programming model) to the BackgroundWorker.
This would not necessarily fit so well with a programming model for command object.
Do you use n-tier (an own application server)?

I haven't used this component myself, but the "simple" solution would be to run the code in "DataPortal_Execute" inside the DoWork method.

Paste code:
I use Productivity Power Tools addin for VS2010 - this allows me to do "HTML Copy" of code.
And IE will paste this into the forum as HTML (Firefox used to allow this but not the latest versions).

tarekahf replied on Wednesday, February 22, 2012

 

Thanks Jonny,

It seems that "BusinessRules.GetAllBrokenRules" is not available in CSLA for .NET 2.0 the one I am using.

Anyway, I don't think I need it, since it is a single level object (but very complex).

I am only concerned about the design of my approach. So seems my appraoch is correct.

Regarding Productivity Power Tools addin, is there one for VS 2005? I am not using VS2010 yet.

Tarek.

 

 

JonnyBee replied on Wednesday, February 22, 2012

Use this one for VS2005 and VS2008. http://copysourceashtml.codeplex.com/

I would prefer to move up to VS2008 or  VS2010 anyway (if possible) and use CSLA N2
http://wwws.lhotka.net/cslanet/N2.aspx

This will give you access to nearly all of C# 3.0 syntax - including lambdas and linq2objects when your project targets .NET 2.0 SP1.

Read more about LinqBridge here: http://www.albahari.com/nutshell/linqbridge.aspx

tarekahf replied on Wednesday, February 22, 2012

Thanks Jonny,

I'll try to move to VS2008 or VS2010 ASAP.

I installed CopyCourseAsHTML (after closing VS2005) from here:

http://copysourceashtml.codeplex.com/releases/view/31130

When I started VS2005 (under Windows 7), I did not see "Copy as HTML". Also, the Add-in Manager box is empty (nothing was installed).

I know this is off-topic, but I appreciate if some one can help me here.

Tarek.

tarekahf replied on Wednesday, February 22, 2012

Oh, many thanks Jonny, now I am able to use CopySourceAsHTML with VS2055.

Here is the latest result (to verify):

    1 

    2     Public Shared Function RefreshDBFields(ByVal theUserCtrlInfoPack As UserCtrlInfoPack, ByVal DoGetCountOnly As Boolean) As RefreshDBFieldsCommand


    3         Dim result As RefreshDBFieldsCommand


    4         If Not AppSecurity.GetSingleton.IsUserAuthorized(AppSecurity.CodesApp.eHRMD, AppSecurity.CodesActions.RefreshDBFlds, AppSecurity.CodesDataTypes.SPMSForm, theUserCtrlInfoPack) Then


    5             Throw New System.Security.SecurityException( _


    6                 String.Format( _


    7                     My.Resources.NotAuthErrorPrm2, _


    8                     theUserCtrlInfoPack.AuthUserID, _


    9                     AppSecurity.CodesActions.RefreshDBFlds.ToString, _


   10                     SPMSForm.GetSPMSFormInits.GetObjectName, "<all>"))


   11         End If


   12         result = DataPortal.Execute(Of RefreshDBFieldsCommand)(New RefreshDBFieldsCommand(theUserCtrlInfoPack, DoGetCountOnly))


   13         Return result


   14     End Function


   15 


   16     <Serializable()> _


   17     Public Class RefreshDBFieldsCommand


   18         Inherits CommandBase


   19 


   20         Private mRecordsToBeRefreshedCnt As Integer


   21         Private mRecordsRefreshedCnt As Integer


   22         Private mDoGetCountOnly As Boolean


   23         Private mRecordVersion As Integer


   24         Private mUserCtrlInfoPack As UserCtrlInfoPack


   25         Private mMessages As New List(Of String)


   26         Private mSuccess As Boolean


   27 


   28         Public ReadOnly Property RecordsToBeRefreshedCnt() As Integer


   29             Get


   30                 Return mRecordsToBeRefreshedCnt


   31             End Get


   32         End Property


   33 


   34         Public ReadOnly Property RecordsRefreshedCnt() As Integer


   35             Get


   36                 Return mRecordsRefreshedCnt


   37             End Get


   38         End Property


   39 


   40         Public ReadOnly Property Messages() As String()


   41             Get


   42                 Return mMessages.ToArray()


   43             End Get


   44         End Property


   45 


   46         Public ReadOnly Property Success() As Boolean


   47             Get


   48                 Return mSuccess


   49             End Get


   50         End Property


   51 


   52         Public Sub New(ByVal theUserCtrlInfoPack As UserCtrlInfoPack, ByVal DoGetCountOnly As Boolean)


   53             mUserCtrlInfoPack = theUserCtrlInfoPack


   54             mDoGetCountOnly = DoGetCountOnly


   55             mSuccess = True


   56         End Sub


   57 


   58         Protected Overrides Sub DataPortal_Execute()


   59             Dim theSPMSForm As SPMSForm = Nothing


   60             Dim theStaffID As String


   61             Dim theReviewFrom As String


   62             Dim theMsg As String


   63             Using cn As New SqlConnection(Database.SPMSFormDB)


   64                 cn.Open()


   65                 Using cm As SqlCommand = cn.CreateCommand


   66                     cm.CommandType = CommandType.StoredProcedure


   67                     cm.CommandText = "uspSPMSFormListGetRecVer"


   68                     cm.Parameters.AddWithValue("@RecVer", SPMSForm.GetSPMSFormInits.RecordVersion)


   69                     mRecordsToBeRefreshedCnt = 0


   70                     mRecordsRefreshedCnt = 0


   71                     Using da As New SqlDataAdapter(cm)


   72                         Using ds As New DataSet


   73                             da.Fill(ds)


   74                             mRecordsToBeRefreshedCnt = ds.Tables(0).Rows.Count


   75                             If Not mDoGetCountOnly Then


   76                                 For Each theRow As DataRow In ds.Tables(0).Rows


   77                                     theStaffID = theRow.Item("StaffID")


   78                                     theReviewFrom = theRow.Item("ReviewFrom")


   79                                     mUserCtrlInfoPack.SetQueryUser(theStaffID)


   80                                     Try


   81                                         theSPMSForm = SPMSForm.GetSPMSForm(cn, mUserCtrlInfoPack, theReviewFrom)


   82                                         theSPMSForm.SetSubmitActionRefreshDBFlds()


   83                                         theSPMSForm.SaveForm()


   84                                     Catch ex As Csla.Validation.ValidationException


   85                                         mSuccess = False


   86                                         mMessages.AddRange(theSPMSForm.BrokenRulesCollection.ToArray())


   87                                     Catch ex As Exception


   88                                         mSuccess = False


   89                                         theMsg = _


   90                                             String.Format(My.Resources.ErrRefreshDBFlds, _


   91                                                         ex.Message, theSPMSForm.GetObjectName(), theSPMSForm.IDStr, _


   92                                                         mUserCtrlInfoPack.AuthUserID)


   93                                         mMessages.Add(theMsg)


   94                                     End Try


   95                                     mRecordsRefreshedCnt += 1


   96                                     theSPMSForm = Nothing


   97                                 Next


   98                                 If mSuccess Then


   99                                     theMsg = _


  100                                         String.Format( _


  101                                             My.Resources.RefreshDBFldsConf, _


  102                                             SPMSForm.GetSPMSFormInits.GetObjectName(), mRecordsRefreshedCnt.ToString, _


  103                                             mRecordsToBeRefreshedCnt.ToString)


  104                                     mMessages.Add(theMsg)


  105                                 End If


  106                             End If


  107                         End Using


  108                     End Using


  109                 End Using


  110             End Using


  111 


  112         End Sub


  113     End Class


Much better !Cool

Copyright (c) Marimer LLC