How can I use AddBusinessRules for a Read Only Object

How can I use AddBusinessRules for a Read Only Object

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


yimiqi posted on Monday, July 16, 2007

I have a read only object that need to call  AddBusinessRules to do some data validations for the user inputs used in search, but I'm getting "ValidationRules.AddRule is not accessible in this context" error as it is protected.  I understand why I'm getting this error is because the Object that calls the "ValidationRule.AddRule" is a Read Only Object, but ValidationRule is defined in BusinessBase.

So is it possible for RO object to use VlidationRule to do any data entry validation then?

Any insights is appreciated. 

RockfordLhotka replied on Monday, July 16, 2007

A read-only object can only have read-only properties (or at least that's all that CSLA supports), so there's never a reason to have validation rules in a read-only object.

If you want to have input fields on your search form, you should bind them to an editable root object - though perhaps one that doesn't actually do any data access. Your read-only list can have a factory that accepts the input object (editable root) as a parameter:

Private Shared Function GetList(userInput As SearchInput)
  ' ...
End Function

The SearchInput class would be an editable root, but with none of the data access code. In other words, it would have only properties and business rules.

yimiqi replied on Tuesday, July 17, 2007

Okay I see.  Thanks Rocky for pointing me at a different direction I never thought of before.

I thought my app only needed read-only and read-only list because it basically emcompasses several search input forms/controls and a list of search results for each search form/control.  Each search result is read-only list, which has a criteria class defined.  Each search form/control is binded to the criteria class (I use it as search criteria).

To clarify, I already have a factory in read-only list that accepts criteria class as a parameter, so what I'm getting at from your solution is that I will need to create an editable root object to replace the criteria class I'm using now to have the search form bind to.  That will allow the search form to have validation rules such as data validation etc.  In this case, criteria class will not be needed any more, right?

My second question on this, would it make difference if I change the criteria to inherit from BusinessBase instead of being created within a read-only list (I'm sure it will)?  I guess my question is what is the difference to create an editable root object vs. use criteria as an editable root object?

Thank you very much for your time and helps.

 

 

JoeFallon1 replied on Tuesday, July 17, 2007

I have a lot of search screens in my app and I created Root BOs with validation rules in them just as Rocky describes. Then when the user clicks Search, the valid BO is passed to the ROC as a parameter and is used to determine which records to fetch.

There are no DataPortal methods - the factory just uses a New constructor to build an instance of the BO.

e.g.

<Serializable()> _
Public Class MySearchCriteriaBO
 
Inherits MyBusinessBase(Of MySearchCriteriaBO)

Joe

RockfordLhotka replied on Tuesday, July 17, 2007

If you don't call the data portal, then you must be doing the data access directly? You'll never be able to use a remote data portal in that case.

What I recommend is passing the valid BO into the ROC factory method as a parameter. In the factory method you should call the data portal, passing a criteria object, and the data load should occur in the ROC's DataPortal_Fetch().

There are a couple ways you can create the criteria object:

Overall I think I'd lean toward that last option: separate BO (with no data access of its own) that is then passed into the Criteria object's constructor and exposed as a property of the Criteria for use in your DP_Fetch() method.

yimiqi replied on Tuesday, July 17, 2007

Thank you both Joe and Rocky for sharing your thoughts and solutions.

In my case (as stated in my previous post), my app is definitely missing an editable root object that allows putting in validation rules. And I will continue to use the data portal to do data access.

I have a few questions for the three options of creating the criteria object Rocky provided:

  • The BO can be a public, nested class inside the ROC: this allows the "criteria" class to inherit from BusinessBase so you can bind it to the UI and is a simple solution - but it is odd to have a public nested class and fxcop will bark at you  >>> Since I already have a public nested "criteria" class defined inside the ROC to be used as search criteria, do I just need to change it to inherit from BusinessBase then put in the validation rules?  This does seem to be a simple solution, but let me read on for more options... 
  • The BO can be a regular, public BO too. Obviously it must inherit from BusinessBase, so it can't inherit from CriteriaBase. So in this scenario the ROC factory method must get the BO data into the Criteria object.   >>>So  I will need to create an editable root object but also need to keep the "criteria" class that I already have to get the BO data into it?  or is the Criteria object noted here referring to the Criteria oject in csla?
  • Overall I think I'd lean toward that last option: separate BO (with no data access of its own) that is then passed into the Criteria object's constructor and exposed as a property of the Criteria for use in your DP_Fetch() method.  >>> I want to try this solution.

    Is the following prototype heading the right direction?  Thanks for your time and help!

    Public Class SearchInput

       Inherits BusinessBase(of SearchInput)

    End Class

    Public Class SearchResultList

       Inherits ReadOnlyListBase(Of SearchResultList, SearchResultInfo)

       Public Shared Function GetSearchResultList(ByVal UserInput As SearchInput) As SearchResultList

          Return DataPortal.Fetch(Of SearchResultList)(New FilteredCriteria(UserInput))

       End Function

       Private Sub New()

       ' require use of factory methods

       End Sub

    <Serializable()> _

    Private Class FilteredCriteria

       Private mUserInput As SearchInput

       Public ReadOnly Property UserInput() As SearchInput

          Get

             Return mUserInput

          End Get

       End Property

       Public Sub New(ByVal UserInput As SearchInput)

          mUserInput = UserInput

       End Sub

    End Class

       Private Overloads Sub DataPortal_Fetch(ByVal criteria As FilteredCriteria)

          Fetch(criteria.UserInput)

       End Sub

    End Class

     

     

    yimiqi replied on Tuesday, July 17, 2007

    Sorry about the formatting of the prototype, I don't know why it turned out that way

    RockfordLhotka replied on Tuesday, July 17, 2007

    Yes, your prototype is headed in the right direction.

     

    Then all you need is SearchInput, which would inherit from BusinessBase, but would only include the Business Methods, Business Rules and Factory Methods regions. The NewInput() factory would be:

     

    Public Shared Function NewInput() As SearchInput

      Return New SearchInput

    End Function

     

    So there’d be no data portal interaction in this class at all.

     

    Rocky

    yimiqi replied on Tuesday, July 17, 2007

    Rocky,

    Thanks so much for your guiding me to the right solution, helping review my prototype and giving valuable advices.  Sure I will remember to only include the Business Methods, Business Rules and Factory Methods regions in the SearchInput BO.

    This is my first app using the csla framework.  With all the kind assistance from this wonderful community, I'm more confident than ever to use the framework.  I also bought and read your book on it, I enjoyed reading the theroy chapters as well as the example chapters.  Excellent book, in my mind.

    Thanks again for all your time.

    JoeFallon1 replied on Wednesday, July 18, 2007

    You got it.

    That is the exact technique I use for my Search screens.

    Joe

     

    yimiqi replied on Wednesday, July 18, 2007

    Good to hear.  Thanks Joe.

    yimiqi replied on Friday, July 20, 2007

    Joe,

    Do you bind your search screen to the BO at design time or run time? Just curious.

    Copyright (c) Marimer LLC