View RSS Feed

jmurrayhead

.NET Business Object Base Class

Rate this Entry
by on January 7th, 2009 at 07:52 PM (3457 Views)
Like my other .NET Development blogs, I preach about building applications with a layered, Object-Oriented architecture. Now I'm going to discuss how to create a base class that all of your business objects can inherit.

This base class will contain methods and properties that, when inherited, will be available to any class that inherits it. In Visual Studio, we will start by creating a new Class Library (*.vb or *.cs) in the App_Code directory. We will name this file BizObject.vb (or BizObject.cs for C#).

Next, we will clear out the contents that are automatically inserted. At the top, we will being importing the namespaces that we plan on using:
Code:
Imports System
Imports System.Data
Imports System.Collections
Imports System.Collections.Generic
Imports System.Web.Caching
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports System.Configuration
Imports System.Web.UI
Imports System.Web.Security
Imports System.Security.Principal
Now, we will enclose our class within its own namespace:
Code:
Namespace DeveloperBarn.SampleApp.BLL
    ' Classes will go here
End Namespace
You can use any naming convention that you want. I typically do something along the lines of "Organization.ApplicationName.Layer". Above, we're dealing with the Business Logic Layer, so the last portion of the namespace is "BLL".

Now onto making the class. We will define this class as Public MustInherit. This simply means that you cannot directly access the methods and properties, (i.e. BizObject.MethodName), it must be inherited and accessed through the class that inherits it.
Code:
Public MustInherit Class BizObject
    ' Methods and properties will be here
End Class
Now, let's create some properties that are commonly used in applications:

Code:
Public MustInherit Class BizObject
    ' We use this for caching, which will be demonstrated at a later time
    Protected Shared ReadOnly Property Cache() As Cache
        Get
            Return HttpContext.Current.Cache
        End Get
    End Property
 
    ' This returns the IPrincipal of the currently logged in user
    Protected Shared ReadOnly Property CurrentUser() As IPrincipal
        Get
            Return HttpContext.Current.User
        End Get
    End Property
 
    ' This returns the username of the currently logged in user
    Protected Shared ReadOnly Property CurrentUserName() As String
        Get
            Dim userName As String = ""
            If HttpContext.Current.User.Identity.IsAuthenticated Then
                userName = HttpContext.Current.User.Identity.Name
            End If
            Return userName
        End Get
    End Property
 
    ' This returns the IP address of the currently logged in user
    Protected Shared ReadOnly Property CurrentUserIP() As String
        Get
            Return HttpContext.Current.Request.UserHostAddress
        End Get
    End Property
Now let's create a method that will purge our cache items based off the supplied key:
Code:
    ''' <summary>
    ''' Remove from the ASP.NET cache all items whose key starts with the input prefix
    ''' </summary>
    Protected Shared Sub PurgeCacheItems(ByVal prefix As String)
        prefix = prefix.ToLower()
        Dim itemsToRemove As New List(Of String)()
 
        Dim enumerator As IDictionaryEnumerator = BizObject.Cache.GetEnumerator()
        While enumerator.MoveNext()
            If enumerator.Key.ToString().ToLower().StartsWith(prefix) Then
                itemsToRemove.Add(enumerator.Key.ToString())
            End If
        End While
 
        For Each itemToRemove As String In itemsToRemove
            BizObject.Cache.Remove(itemToRemove)
        Next
    End Sub
End Class
Here is the entire BizObject.vb file:
Code:
Imports System
Imports System.Data
Imports System.Collections
Imports System.Collections.Generic
Imports System.Web.Caching
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports System.Configuration
Imports System.Web.UI
Imports System.Web.Security
Imports System.Security.Principal
 
Namespace DeveloperBarn.SampleApp.BLL
    Public MustInherit Class BizObject
        ' We use this for caching, which will be demonstrated at a later time
        Protected Shared ReadOnly Property Cache() As Cache
            Get
                Return HttpContext.Current.Cache
            End Get
        End Property
 
        ' This returns the IPrincipal of the currently logged in user
        Protected Shared ReadOnly Property CurrentUser() As IPrincipal
            Get
               Return HttpContext.Current.User
            End Get
        End Property
 
        ' This returns the username of the currently logged in user
        Protected Shared ReadOnly Property CurrentUserName() As String
            Get
                Dim userName As String = ""
                If HttpContext.Current.User.Identity.IsAuthenticated Then
                    userName = HttpContext.Current.User.Identity.Name
                End If
                Return userName
            End Get
        End Property
 
        ' This returns the IP address of the currently logged in user
        Protected Shared ReadOnly Property CurrentUserIP() As String
            Get
                Return HttpContext.Current.Request.UserHostAddress
            End Get
        End Property
 
        ''' <summary>
        ''' Remove from the ASP.NET cache all items whose key starts with the input prefix
        ''' </summary>
        Protected Shared Sub PurgeCacheItems(ByVal prefix As String)
            prefix = prefix.ToLower()
            Dim itemsToRemove As New List(Of String)()
 
            Dim enumerator As IDictionaryEnumerator = BizObject.Cache.GetEnumerator()
            While enumerator.MoveNext()
                If enumerator.Key.ToString().ToLower().StartsWith(prefix) Then
                    itemsToRemove.Add(enumerator.Key.ToString())
                End If
            End While
 
            For Each itemToRemove As String In itemsToRemove
                BizObject.Cache.Remove(itemToRemove)
            Next
        End Sub
    End Class
 End Namespace
Now our base class is completed. Here is an example of a class that inherits the BizObject class:
Code:
Imports Microsoft.VisualBasic
 
Namespace DeveloperBarn.SampleApp.BLL.Users
    Public MustInherit Class BaseUser
        Inherits BizObject
 
#Region "Methods"
        Protected Shared Sub CacheData(ByVal key As String, ByVal data As Object)
            If Settings.EnableCaching AndAlso Not IsNothing(data) Then
                BizObject.Cache.Insert(key, data, Nothing, _
                    DateTime.Now.AddSeconds(Settings.CacheDuration), TimeSpan.Zero)
            End If
        End Sub
#End Region
    End Class
End Namespace
Above, I have another base class which is used for a Users object. Typically, this class would contain private variables, properties, constructors, etc. But that is out of scope for this entry and will be touched on at a later time. Do notice, however, the CacheData method. This is called whenever you retrieve data from the database that you want to be cached on the server to prevent multiple calls to the database. This works with the PurgeCacheItems method to manage the application cache. You will call PurgeCacheItems any time you Create, Update or Delete records. Simply provide these methods a key (using the same key for each class) and they will do the rest.

For example, let's say you retrieve a list of users. You may have something like this:
Code:
Public Shared Function GetAllUsers() As List(Of User)
    ' Check if the object is already in cache
    Dim appUser As List(Of User) = Nothing
    Dim key As String = "users_user"
 
    If Not IsNothing(BizObject.Cache(key)) Then
        appUser = CType(BizObject.Cache(key), List(Of User))
    Else
        ' Perform a call to the data access layer (to be discussed later), retrieve the results and cache them
        Dim recordset As List(Of UserDetails) = _
                    SiteProvider.Users.GetAllUsers
        appUser = GetUserListFromUserDetailsList(recordset)
                BaseUser.CacheData(key, appUser)
    End If
 
    Return appUser        
End Function
Now, much of the code here might not make much sense to you now because I'm using methods from my own Data Access Layer. If you don't know anything about business objects, read my blog here: Building Applications with a Business Object Architecture - DeveloperBarn Forums
Basically, the above code is calling the Data Access Layer to populate a business object which is then cached.

Finally, whenever Create, Update or Delete methods are called, using the same key as above for this class, call the PurgeCacheItems method to clear the cache. This method will clear all cache items with keys beginning with "users_user".
Code:
BizObject.PurgeCacheItems("users_user")
That's it! Now you have a base class that can be inherited to reuse methods and properties that are often used.

Submit ".NET Business Object Base Class" to Digg Submit ".NET Business Object Base Class" to del.icio.us Submit ".NET Business Object Base Class" to StumbleUpon Submit ".NET Business Object Base Class" to Google

Updated May 9th, 2011 at 11:30 AM by jmurrayhead

Categories
Programming & Scripting , ASP.NET

Comments

  1. micky -
    micky's Avatar
    I have a question J!
    I think this cache must be stored on server itself like sessions.
    Is it right?

    If yes, then wont they take server's resources in the same way?
    • |
    • permalink
  2. jmurrayhead -
    jmurrayhead's Avatar
    That's correct, M. However, it's only stored for a specified period of time. If you notice a problem with server performance, although I doubt you will, you can determine which objects you want to cache.
    • |
    • permalink
  3. micky -
    micky's Avatar
    Hmm, so howz this better than sessions?
    Also i never faced problems with sessions either

    So if it is stored in same way as sessions and can effect server's performance in same way, so why write so much of code?
    • |
    • permalink
  4. jmurrayhead -
    jmurrayhead's Avatar
    It uses HttpContext.Current, which is the current session. I never said otherwise

    Caching data reduces calls to the database. You should be able to see the benefit of having a database with fewer connections and what not. All the code allows for an easy way to manage the cache. It's really not that much code and the class can be inherited by every class that requires caching. So you're essentially only calling one line of code, MyClass.CacheData() and BizObject.PurgeCacheItems(), where needed.
    • |
    • permalink
  5. micky -
    micky's Avatar
    I understand all the benefits J

    My only question is how its better than having a value in a session?
    • |
    • permalink
  6. jmurrayhead -
    jmurrayhead's Avatar
    M,

    The methods above use the Cache property of the HttpContext.Current object. Sessions may change from user to user while cache will be applicable to the entire application throughout its life cycle, thus improving overall application performance. Cache will always be in memory, even if you use a separate Session State Server or SQL Server, thus retaining its performance advantages. Also, it is managed by ASP.net, so for example, you can give priorities to cache items for ASP.net to automatically purge if they are not used often, or memory gets full, which gives even more performance advantages.

    I retract my statement above, in which session and cache are the same, as they are not. They are similar, but with great differences.
    • |
    • permalink
  7. micky -
    micky's Avatar
    Now you are talking man

    It makes sense to me now....... thanx
    • |
    • permalink

SEO by vBSEO