Lazy loading (or deferred or on-demand loading) of a child object is
relatively easy to implement in CSLA .NET.
Make sure to
apply this errata before proceeding.
The idea is that a child object or child collection is not loaded from the
database when the root object is loaded, but rather on the first (if any)
attempt by client code to access the child data. This is only a good idea if the
typical usage of the parent object does not require the child data. If
the child data actually gets used it is far more efficient to load all the data
at once than to use lazy loading. However, if 80% of the time the child data is
not used then lazy loading can make a lot of sense.
For instance, if we have a Contact root object, which has a collection of
child Detail objects that are rarely accessed then we can use lazy loading on
the Detail collection.
Implementing this requires a bit of attention on our part as developers
because we need to add extra code any time we direct access the Private field
holding the child collection (or object) reference. Any time we reference this
variable, we need to see if it is Nothing, and if so we need to trigger a load
operation.
The exception is in the DataPortal_Update method, where if the child variable
is Nothing then we simply ignore it. If the data was never loaded, then there's
nothing to update.
To pursue the Contact/Detail example, in the Contact class we'd have a
variable to store the child collection:
Private
mDetails As
Details = Details.NewDetails()
We'd also have a property to expose this to clients, where we'd use lazy
loading:
Public
ReadOnly
Property Details()
As Details
Get
If mDetails Is
Nothing Then
mDetails = Details.GetDetails(Me.ID)
End If
Return
mDetails
End
Get
End
Property
In many cases, this is the only code in the parent object that deals with the
mDetails variable, and if so then we should be all set. If there is other code
that directly accesses the mDetails variable, it should be changed to use the
Details property instead, thus centralizing the lazy loading operation. If that
is not possible, then the lazy loading code will need to be duplicated anywhere
the mDetails variable is used.
We then need to make sure that we don't have any Details in the case that
we've loaded the Contact object from the database. This requires a change to the
DataPortal_Fetch in Contact. In pseudo-code it is like this:
Protected
Overrides
Sub DataPortal_Fetch(ByVal
Criteria As
Object)
' load Contact data as normal
' instead of loading Details, we set it to
Nothing
mDetails =
Nothing
End
Sub
By setting mDetails to nothing, we ensure that subsequent attempt to access
this information will trigger the lazy load operation. Notice that we didn't
load the data here, we just defer the load until sometime in the future (maybe).
The only other change is in the DataPortal_Update of the Contact class. In
pseudo-code it is like this:
Protected
Overrides
Sub DataPortal_Update()
' save Contact data as normal
If
Not mDetails
Is
Nothing
Then
mDetails.Update(Me)
End
If
End
Sub
We only update the child data if we have actually loaded child data.