MarkNew overwrites MarkOld in DataPortal.Create

MarkNew overwrites MarkOld in DataPortal.Create

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


Henrik posted on Monday, September 18, 2006

I just came across a little problem in CSLA 2.0+

I have a situtation where I create an enrolment object with an identification number (a danish personnumber like an american SSN). If the database doesn't have a person with this number, the create method should create a new person. If the number exists, the create method must load the existing person and mark itself as old.

However if I mark the person as old in DataPortal_Create, it get's overwritten by the SimpleDataPortal. Looking into BusinessBase in Csla, I found that the Create method first calls the DataPortal_Create of the subclass and then marks the object as new.

Will it cause any problems, if I move the MarkNew call up before the call to the subclass.DataPortal_Create?

TIA
/Henrik

RockfordLhotka replied on Monday, September 18, 2006

I think a better solution is to use an actual private factory object - typically derived from ReadOnlyBase -
to retrieve the object. Since you aren't really doing a strict "create" or "fetch", a factory is a better answer.

<Serializable()> _
Public Class Enrollment

  Public Shared Function GetEnrollment(...) As Enrollment
    Return EnrollmentFactory.GetEnrollment(...)
  End Function

  Friend Shared Function LoadEnrollment(dr As Datareader) As Enrollment
    Fetch(dr)
  End Function

  <Serializable()> _
  Private Class EnrollmentFactory
    Public Shared Function GetEnrollment(...)
      Return DataPortal.Fetch(Of EnrollmentFactory)(New Criteria(...)).Result
    End Function

    private _result As Enrollment
    Public ReadOnly Property Result() As Enrollment
      Get
        Return _result
      End Get
    End Property

    Private Overloads Sub DataPortal_Fetch(...)
      ' get datareader (dr)
      If dr.Read() Then
        _result = Enrollment.LoadEnrollment(dr)
      Else
         _result = DataPortal.Create(Of Enrollment)()
      End If
    End Sub
  End Class

  Protected Overrides Sub DataPortal_Create()
    ' load new object defaults here
  End Sub

  Private Sub Fetch(dr As Datareader)
    ' load data from datareader
    MarkOld()
  End Sub

  ' note that DataPortal_Fetch() is NOT implemented or used!!

End Class

Henrik replied on Monday, September 18, 2006

Thanks Rocky

I re-read my question and noted that I didn't explain myself fully. Anyway your proposal of a factory class solves my problem elegantly.

I have en enrolment class that embeds a child class for the child being enrolled.

Enrolment

   Child


What I did wrong was having the child’s DataPortal_Create detect whether another child already exists with the specified identification number. I have moved this logic into the enrolment class DataPortal_Create and created a ChildFactory. The ChildFactory class looks like this.

 

<Serializable()> _

Public NotInheritable Class ChildFactory

   Public Shared Function GetChild(ByVal identificationNumber As String) As Child

       Dim cem As DataCard.Child.ChildExistCommand

       cem = DataCard.Child.ChildExistCommand.Execute(identificationNumber)

       If cem.Exist Then

          Return Child.Load(cem.PartyId)

       Else

          Return Child.Create(identificationNumber)

       End If

   End Function

End Class

 

and the DataPortal_Create of the enrolment class now looks like this:

 

Private Overloads Sub DataPortal_Create(ByVal crit As Criteria)

   _child = DataCard.ChildFactory.GetChild(crit.IdentificationNumber)

   ValidationRules.CheckRules()

End Sub

 

This is much cleaner than my previous attempt.

 

Thanks again

/Henrik

 

Copyright (c) Marimer LLC