Click here to Skip to main content
Licence CPOL
First Posted 16 Feb 2008
Views 25,533
Bookmarked 26 times

Singleton Collection in VB.NET

By Jason Witty | 16 Feb 2008
Example of a proper Singleton collection in Visual Basic .NET
3 votes, 30.0%
1
1 vote, 10.0%
2

3
1 vote, 10.0%
4
5 votes, 50.0%
5
2.80/5 - 11 votes
μ 2.80, σa 3.32 [?]

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 have 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, every time 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 one user on your site, then this happens once, but if there are thousands of users on your site at once this is happening 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 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 their 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 one 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 your 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 instances 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_someprocedure")
            While reader.Read
                Try
                    'init
                    Dim a As New Aricle()
                    'load data
                    ....
                    ....
                    al.Add(a.ArticleID, a)
                Catch ex As Exception
                'log error and move to next row
                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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jason Witty

Software Developer (Senior)

United States United States

Member
For more articles please visit my website:
http://www.aprogrammersjournal.com
 
A Programmers Journal
RSS

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralPros & cons Pinmemberneil_b21:05 18 Feb '08  
GeneralRe: Pros & cons PinmemberJason Witty6:22 19 Feb '08  
GeneralConcurrency issues PinmemberMember 364034621:04 18 Feb '08  
GeneralRe: Concurrency issues PinmemberJason Witty6:40 19 Feb '08  
First of there is something inheritly wrong with your question above. It would be against best practices to ever store information such as customer data or order data in any type of collection that would be accessible to others users. This would not be an example of using a singleton collection properly.
 
A better example in an ecommerce system would be a collection of products that are sold on your web site. This type of collection would be better suited for a singleton collection because of the following reasons.
 
1. The data is requested at a very high rate and you want to limit round trips from your database.
2. The same exact data is requested every time for each user.
3. The majority of the requests for this data are read read requests, not write requests.
4. The data stored is specific to your web application not the user of your web application.
 
After saying that I will attempt to address your concerns. As I said in another comment below thread safety on edits, deletes and inserts could be achieved in the same fashion(using SyncLock) that is achieved in the initial loading of data in my example above. A SyncLock block will ensure that only one thread can run the code block enclosed within it at one time. Like I said you would also need to shadow other public properties from your base class that could give a developer access to the object outside of the SyncLock. But overall yif you are concerned about this a Singleton object may not be the best choice in the first place !
 
In a clustered hosting environment a simple handler can be added to your web application to update the data or simply clear the data from a centralized server.
 
For instance on an ecommerce web site if your were storing your products in a singleton collection you would most likely have a content management system that users would use to manage these products. The content management system would simply call the handlers on the web servers to tell them that data has been updated, they could hand them the new data or simply instruct them to reload the data from the database.
 

Generalcouple of things.... PinmemberNirosh6:29 17 Feb '08  
GeneralRe: couple of things.... PinmemberJason Witty6:54 17 Feb '08  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120210.1 | Last Updated 16 Feb 2008
Article Copyright 2008 by Jason Witty
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid