Skip Navigation Links Front Page > Archive > Specific Article
posted on:2/17/2008

results

Introduction

I have seen many articles written about this subject for .net. The problem is that there is something wrong or left out of all of them. Most demonstrate the pattern properly but leave some important information out when it comes to an actual implementation. In the example below I show you how to create a useful singleton business object class which will load data from the database, persist itself within the application, account for inserts and updates properly, only allow one instance of itself and has the ability to be reloaded.

Background

A singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. This can be extremely useful in a .net web application. In a typical web application everytime a user requests a page a transaction is sent to the database, the database returns the data, the data is then read into an object and then displayed. If there is 1 user on your site, then this happens once, but if there are thousands are users on your site at once this is happenning thousands of times. This means thousands of requests to your database and thousands of processor ticks constructing and deconstructing your objects all for the same exact data! In the example below the data is loaded from your database the first time it is requested and stored at the application level. This means that it all of your users will use the same data, no need for constant round trips back to the database. It also counts for the need to update and insert data, as well as the ability to reload your data as need be.

Using the code

As a base we start by inheriting a generic dictionary of a fictional business object article. We choose the dictionary object because it allows us to index to specific objects by thier key. We never need to loop through our collection to find an object if we know the id. Another thing to note is the use of the SyncLock, the reason this is there is because there is a possibility that a user will try to load data while another user is loading it. The lock only allows 1 instance of that code to be run at once, all others wait in queue. The second test will allow the users in queue to pick up the object after it has been loaded. Lastly you will notice that there are two methods named editarticle and addarticle, the use of these methods will both insert the data into you singleton object as well as the database. Thus not forcing you to reload your object and allowing your data to be safe and secure in the database ready for the next reload.

''' <summary>

''' ArticleList

''' </summary>

''' <remarks>

''' Singleton Collection of articles

''' </remarks>

Public Class ArticleList

   Inherits Generic.Dictionary(Of Integer, Aricle)

   ''' <summary>

   ''' SyncLock_LOCK

   ''' </summary>

   ''' <remarks></remarks>

   Private Shared ReadOnly SyncLock_LOCK As New Object()

   ''' <summary>

   ''' Instance

   ''' </summary>

   ''' <remarks>

   ''' The current running instance.

   ''' </remarks>

   Private Shared m_instance As ArticleList

   Public Shared ReadOnly Property Instance() As ArticleList

      Get

         ' initialize if not already done

         If m_instance Is Nothing Then

            'only allow 1 person to load data at once.

            SyncLock SyncLock_LOCK

               If m_instance Is Nothing Then

                  m_instance = LoadData()

                  'update time cache was loaded.

                  System.Web.HttpContext.Current.Application("CacheTime") = DateTime.Now()

               End If

            End SyncLock

         End If

      ' return the initialized instance of the Singleton Class

      Return m_instance

   End Get

End Property

 

''' <summary>

''' New

''' </summary>

''' <remarks>

''' Private Constructor

''' Do not allow multiple intances of class to be created.

''' </remarks>

Private Sub New()

End Sub

 

''' <summary>

''' LoadData

''' </summary>

''' <remarks></remarks>

Private Shared Function LoadData() As ArticleList

   Dim al As New ArticleList()

   Using reader As SqlClient.SqlDataReader = DataAccess.ExecDataReader("sp_...")

      While reader.Read

         Try

            'init

            Dim a As New Aricle()

            'load data

            ...

            'add to shared instance.

            al.Add(a.ArticleID, a)

         Catch ex As Exception

            'skip article

         End Try

       End While

   End Using

Return al

End Function

 

''' <summary>

''' AddArticle

''' </summary>

''' <param name="key"></param>

''' <param name="value"></param>

''' <remarks></remarks>

Public Sub AddArticle(ByVal key As Integer, ByVal value As Aricle)

   'add article to collection.

   MyBase.Add(key, value)

   'code to insert to database goes here.

End Sub

 

''' <summary>

''' EditArticle

''' </summary>

''' <param name="key"></param>

''' <param name="value"></param>

''' <remarks></remarks>

Public Sub EditArticle(ByVal key As Integer, ByVal value As Aricle)

   'edit in memory

   m_instance(key) = value

   'code to update your db goes here.

End Sub

 

''' <summary>

''' ReloadData

''' </summary>

''' <remarks></remarks>

Public Shared Sub ReloadData()

   m_instance = Nothing

End Sub

End Class


Points of Interest

This is a nice alternative to using web.caching to persist data in memory and should give your web application that boost it was looking for. Just please be aware that if you try to load 300 megs of memory into a singleton object your asp.net worker process will take a dive. Design your applications carefully and make the best choices based on your situation.




Comments For This Article:

The reload data is not smart, as it will destroy the original instance and create a new one on first usage. However if somewhere you ahve a ref to that original singleton instance it will be lost.

A better solution is to place th ecode for reloading the data in its own class, and to call that from the private constructore. For the ReloadData method, you would then first test to see if there is an instance, and if so then call the reload data mehod on that instance.


 

posted on: 11/22/2009 12:55:04 AM by Michael Khalsa


Post A Comment:

  Your Name:


  Your Comment:

  Please Enter The Captcha Image: