Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Distributed Applications / August 2003

Tip: Looking for answers? Try searching our database.

Partially loading objects

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Stephen Muecke - 21 Aug 2003 01:21 GMT
I am seeking some advice on my methodology for minimising data transfer

I am developing an application that will manage all contractual requirements
of a construction project
In simple terms, an organisation will have a collection of projects, each
project has a collection of contracts and each contract will have various
collections of documents (claims, variations, time extensions etc). A
typical user would have access to about 2000 documents but in any one
session would probably only access a handful of these

Since every object contains an ID(int) and Name(varchar 100) field, my
proposal is to use a simple structure (sDocument) as a proxy to initially
retrieve the various lists of documents on demand.

In data tier (ContractData class)

Public Function GetVariations(ByVal contractID as Integer) as sDocument()
 ..User DataReader to read variations (stored procedure returns only ID and
Name fields)
 ..Create a new sDocument structure for each read
 ..Return an array of sDocument (typically between 20 an 100 depending on
the type of contract)
End Function

In business tier (ContractCollection class)

Public ReadOnly Property Variations() as VariationCollection
 If Not m_IsLoaded Then
   m_Variations = New VariationsCollecton
   ..Call GetVariations to return array of sDocument
   ..Create a new variation for each sDocument in the array and add to
collection
   m_IsLoaded = True
 End If
 Return m_Variations
End Property

At this point I can display the documents in a treeview or whatever using
the Name property.  If the user selects a document for viewing or editing,
the detail data is then loaded.

In business tier (Variation class)

Public Property Description() as String
 Get
   'Check if the detail data has been loaded from the database
   If Not m_IsLoaded
     LoadData()
   End If
   Return m_Description
 End Get
 ....

Private Sub LoadData()
 ..Call the method in the data tier that returns a structure (sVariation)
containing the detailed data for a variation
 ..Set each property (m_Description = sVariation.Description....)
 m_IsLoaded = True

Is this a reasonable approach or is there a better way?

Stephen
Jay B. Harlow [MVP - Outlook] - 21 Aug 2003 03:36 GMT
Stephen,
Yours is the common way of implementing the Lazy Load pattern.

http://www.martinfowler.com/eaaCatalog/lazyLoad.html

One variation I have used that avoids the conditional, is a State Pattern
using Delegates that has 2 states. Rather than have a boolean data loaded
switch, have a Delegate that represents either loaded data or need to load
data.

The delegate is loaded with the address of the routine to load data in the
constructor. Each property simply invokes the delegate. Seeing as its the
LoadData routine, the data is loaded for the class, the last thing the
LoadData routine does is set the delegate to a dummy routine that does
nothing. Subsequent invokes will simply return.

The methods are a little shorter (avoided if statement) at the expense of a
delegate invoke.

Something like:
   Delegate Sub LoadDataHandler()

   Private m_loaded As LoadDataHandler

   Public Sub New
       m_loaded = AddressOf LoadData
   End Sub

> Public Property Description() as String
>   Get
       m_loaded.Invoke()
>     Return m_Description
>   End Get

   Private Sub LoadData()
>   ..Call the method in the data tier that returns a structure (sVariation)
> containing the detailed data for a variation
>   ..Set each property (m_Description = sVariation.Description....)
       m_loaded = AddressOf DataLoaded
   End Sub

   Private Sub DataLoaded()
       ' This space intentionally left blank
   End Sub

Either a delegate or a boolean if are good methods to implement a lazy load.

Hope this helps
Jay

> I am seeking some advice on my methodology for minimising data transfer
>
[quoted text clipped - 58 lines]
>
> Stephen
Stephen Muecke - 21 Aug 2003 04:32 GMT
Thanks Jay,
I must start learning more about patterns

One more question (and I'm sure this is probably another pattern)
Every document contains information about the author and last modifier of
the document

Public ReadOnly Property Author() as Person
Public Property Modifier() as Person

My methodology is to create a singleton UserCollection class containing a
collection of Persons (in the Business layer)
When a document is loaded (in detail), it would search the UserCollection
and if not found, create a new person from the database and add it to the
collection. Something along the lines of

In the UserCollection class

Friend Function FindByID(ByVal ID as Integer) as Person
 'Loop through each person and find the matching ID
 ..or maybe use HashTable to retrieve Person by ID?
 Dim user As Person
 For Each user In MyBase.List
   If user.ID = ID Then
     Return user
   End If
 Next
 'If we got this far, the person is not in the collection so load it
 Dim proxy as sDocument = <Call the data tier to return a sDocument of the
person identified by ID>
 Dim user as New Person(proxy.ID, proxy.Name)
 'Add the person to the collection
 MyBase.List.Add(user)
 Return user
End Function

Stephen

> Stephen,
> Yours is the common way of implementing the Lazy Load pattern.
[quoted text clipped - 110 lines]
> >
> > Stephen
Jay B. Harlow [MVP - Outlook] - 21 Aug 2003 15:21 GMT
Stephen,
> I must start learning more about patterns
Yes patterns are good to know! The three books I would recommend include:
1. "Design Patterns - Elements of Reusable Object-Oriented Software" by GOF
(gang of four = Erich Gamma, Richard Helm, Ralph Johnson, & John Vlissides)
2. "Visual Basic Design Patterns - VB 6.0 an VB.NET" by James W. Cooper
3. "Patterns Of Enterprise Application Architecture" by Martin Fowler

All three from Addison Wesley.

Is there a question in there? :-)

You describe a Person Collection that sounds like the Repository Pattern.
http://www.martinfowler.com/eaaCatalog/repository.html

Is this your question?
>   'Loop through each person and find the matching ID
>   ..or maybe use HashTable to retrieve Person by ID?

Seeing as Person has an ID, I would use a HashTable, I would derive from
DictionaryBase actually, as the retrieval by ID (key) is quicker. Also
consider storing a System.WeakReference to Person, instead of Person
directly. Especially if the Person object is fairly large. Unless you
already have a method of cleaning up unused Person objects in the
collection.

The GC knows about WeakReferences, when a Garbage Collection occurs the
objects referenced by WeakReferences are discarded if there are no other
references to that object. If your program currently is using the Person its
safe, if the Person only exists in the Collection its toast.

Then you need to modify the 'FindByID' that if it finds a WeakReference with
Target property Nothing, then you need to load the object again.

Something like:
   ' Assumes collection inherits from DictionaryBase
> Friend Function FindByID(ByVal id as Integer) as Person
   Dim wr As WeakReference
   Dim person As Person
   If InnerHashtable.Contains(id) Then
       wr = DirectCast(InnerHashtable(id), WeakReference)
       person = DirectCast(wr.Target, Person)
       If person Is Nothing Then
           person = CreatePerson(id)
           wr.Target = person
       End If
   Else
       person = CreatePerson(id)
       wr = New WeakReference(person)
       InnerHashTable.Add(person.ID, person)
   End If
   Return person
> End Function

   ' A factory pattern
   Private Function CreatePerson(Byval id as integer) as Person
       Dim proxy as sDocument = <call data tier>
       return new Person(id, proxy)
   End Function

The problem now becomes your collection can fill up with unused
WeakReferences. I would probably have a timer event in the collection that
looks for weak references and cleans them out. Also make sure you coordinate
the cleanup process correctly with your find process, you don't want an
entry disappearing while you are recreating it...

Hope this helps
Jay

> Thanks Jay,
> I must start learning more about patterns
[quoted text clipped - 33 lines]
>
> Stephen

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.