Cache Frequently-Used Data in the Application or Session Objects
ASP Application and Session objects are like handy storage lockers in your app's memory. You can stash data in either one, and it'll stay put even when users hop between pages. But remember:
Session data gets a separate locker for each user. It's perfect for things like shopping cart contents or user preferences.
Application data has just one shared locker for everyone. Use it for info that's the same across the board, like a list of product categories or company contact details.
When to load data into these lockers? You've got options:
Load it right when the Application or Session starts: Add your code to the
Application_OnStart()
orSession_OnStart()
functions in theGlobal.asa
file.Load it only when you actually need it: This is like only unpacking your suitcase when you find the outfit you want. It's called "lazy evaluation" and can give your app a performance boost. Just add a check to your ASP pages to see if the data's already there, and load it if it's not.
Choose the loading strategy that best suits your app's needs and data usage patterns.
An example:
<%
Function GetEmploymentStatusList
Dim d
d = Application("EmploymentStatusList")
If d = "" Then
' FetchEmploymentStatusList function (not shown)
' fetches data from DB, returns an Array
d = FetchEmploymentStatusList()
Application("EmploymentStatusList") = d
End If
GetEmploymentStatusList = d
End Function
%>
Similar functions could be written for each chunk of data needed.
When it comes to storing data in Application or Session objects, you've got freedom of choice! They happily house any kind of data you throw at them, from simple numbers and text to complex arrays.
One common scenario is storing ADO recordsets. While you could manually copy each field into separate variables, there's a faster and more elegant way:
Use ADO's handy recordset persistence functions to package the data up neatly:
GetRows() transforms the recordset into a handy array, perfect for quick access and manipulation.
GetString() condenses it into a single string, ideal for compact storage or file operations.
Save() (in ADO 2.5) lets you create a disk-based snapshot, offering persistence beyond memory.
While I can't dive into the details of each function here, I'll gladly demonstrate how to use GetRows() to fetch an array of recordset data. Check out this code example:
' Get Recordset, return as an Array
Function FetchEmploymentStatusList
Dim rs
Set rs = CreateObject("ADODB.Recordset")
rs.Open "select StatusName, StatusID from EmployeeStatus", adoCon
FetchEmploymentStatusList = rs.GetRows() 'Return data as an Array
rs.Close
Set rs = Nothing
End Function
A further refinement of the above might be to cache the HTML for the list, rather than the array. Here's a simple sample:
' Get Recordset, return as HTML Option list
Function FetchEmploymentStatusList
Dim rs, fldName, s
Set rs = CreateObject("ADODB.Recordset")
rs.Open "select StatusName, StatusID from EmployeeStatus", adoCon
s = "<select name='EmploymentStatus'>" & vbCrLf
Set fldName = rs.Fields("StatusName") ' ADO Field Binding
Do Until rs.EOF
' Next line violates Don't Do String Concats,
' but it's OK because we are building a cache
s = s & " <option>" & fldName & "</option>" & vbCrLf
rs.MoveNext
Loop
s = s & "</select>" & vbCrLf
rs.Close
Set rs = Nothing ' See Release Early
FetchEmploymentStatusList = s ' Return data as a String
End Function
Caching ADO recordsets directly in Application or Session scope is possible, but it comes with two strict rules:
ADO must be free-threaded: This ensures it plays nicely with multiple users accessing the data simultaneously.
The recordset must be disconnected: It should be independent of the database connection to avoid resource conflicts.
If you can't guarantee these conditions, don't cache the recordset. Storing COM objects like ADO recordsets can lead to trouble if not handled carefully (more on that in the Non-Agile Components and Don't Cache Connections tips).
Once data is in Application or Session scope, it stays there until:
You change it programmatically
The session ends (for Session data)
The web app restarts (for Application data)
Need to update cached data? You have options:
Manual refresh: Create an admin-only ASP page to trigger updates when needed.
Automatic refresh: Use a function to periodically check timestamps and refresh data after a set time interval. Here's an example of how to do this:
<%
' error handing not shown...
Const UPDATE_INTERVAL = 300 ' Refresh interval, in seconds
' Function to return the employment status list
Function GetEmploymentStatusList
UpdateEmploymentStatus
GetEmploymentStatusList = Application("EmploymentStatusList")
End Function
' Periodically update the cached data
Sub UpdateEmploymentStatusList
Dim d, strLastUpdate
strLastUpdate = Application("LastUpdate")
If (strLastUpdate = "") Or _
(UPDATE_INTERVAL < DateDiff("s", strLastUpdate, Now)) Then
' Note: two or more calls might get in here. This is okay and will simply
' result in a few unnecessary fetches (there is a workaround for this)
' FetchEmploymentStatusList function (not shown)
' fetches data from DB, returns an Array
d = FetchEmploymentStatusList()
' Update the Application object. Use Application.Lock()
' to ensure consistent data
Application.Lock
Application("EmploymentStatusList") = d
Application("LastUpdate") = CStr(Now)
Application.Unlock
End If
End Sub
For another example, see World's Fastest ListBox with Application Data.
Hold on before stuffing those huge arrays into Session or Application objects! It might sound convenient, but it can backfire in a big way. Here's why:
Every time you need to access even a single element, the entire array gets duplicated. Imagine a 100,000-item array of zip codes and weather stations. Just to grab one string, ASP would have to create a whole temporary copy of all those stations. Talk about a waste of resources!
For large datasets like this, explore better alternatives:
Custom components: Build a tailored solution with efficient methods for storing and retrieving data.
Dictionaries: These handy structures offer faster lookups than arrays for non-contiguous key-value pairs.
But remember:
Arrays still reign supreme for lightning-fast access to contiguous data. Don't discard them completely!
Choose wisely based on your specific needs and performance goals. The right data structure can make a world of difference.
Original Source: https://axcs.blogspot.com/2006/07/asp-tips-tip-2-cache-frequently-used.html
Subscribe to my newsletter
Read articles from Edward Anil Joseph directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by