xpo-2051-examples-how-to-handle-persistent-object-initialization.md
Persistent objects represent an object that exists in some manner between program runs. During program execution, it is represented by non-persistent object instances, thus loading an object from a database is not actually the construction of a new object, but the restoration of an object’s state. Here we consider two types of object constructors: actual constructor and default persistent object instance constructor. The former is used to create an object for the first time. The latter is called before loading an object’s state from a database. Base XPObject classes have only a default constructor without parameters to prepare an object’s instance for loading. Avoid placing any new object initialization logic into the default constructors, create a new constructor and use it to create new persistent objects instead:
// Represent the Contact class which contains employment information.
public class Contact: Person {
public Contact(): base() {}
// References the contact's employer which is passed as a constructor's parameter.
public Contact(Company employer): base() {
this.Employer = employer;
}
// ...
}
' Represent the Contact class which contains employment information.
Public Class Contact : Inherits Person
Public Sub New()
MyBase.New()
End Sub
' References the contact's employer which is passed as a constructor's parameter.
Public Sub New(ByVal _employer As Company)
MyBase.New()
Me.Employer = _employer
End Sub
' ...
End Class
Naturally, object properties will be assigned during object state loading, but this assignment is not associated with object interface logic, and sometimes must be handled differently. As an example, consider the NameModified property that is set to true whenever the Name property is changed. When the object is loaded from a database, the Name property is assigned a value and this should be treated not as a name modification, but as an initialization. You can use the PersistentBase.IsLoading property to detect an object’s initialization. During initialization it will be set to true , otherwise it will be false :
public class Contact: Person {
// ...
Company employer = null;
public Company Employer {
get { return employer; }
set {
employer = value;
// Adds the employer's default address information to the contact's addresses.
if (!IsLoading && employer != null && employer.DefaultAddress != null) {
Addresses.Remove(DefaultAddress);
DefaultAddress = new Address(employer.DefaultAddress);
Addresses.Add(DefaultAddress);
}
}
}
}
Public Class Contact : Inherits Person
' ...
Private _employer As Company = Nothing
<Persistent("CompanyID")> _
Public Property Employer() As Company
Get
Return _employer
End Get
Set(ByVal Value As Company)
_employer = Value
' Adds the employer's default address information to the contact's addresses.
If (Not IsLoading) Then
If ((Not (_employer Is Nothing)) And (Not (_employer.DefaultAddress Is Nothing))) Then
Addresses.Remove(DefaultAddress)
DefaultAddress = New Address(_employer.DefaultAddress)
Addresses.Add(DefaultAddress)
End If
End If
End Set
End Property
End Class
The IXPObject.OnLoaded virtual method is called when an object’s state is completely restored from a database. You can override it if you want to perform additional housekeeping after initialization, because you cannot use constructors for this purpose.
See Also