Introduction
This is a very short article to help people who use SQL Sessions. As everybody knows, storing Sessions on your SQL Server is a great idea, however is also a performance nightmare. If you are using Sessions as much as I do, your SQL Server is just a little too busy retrieving Sessions here and there. So let me show you what I do in order to avoid round trips to SQL Server and use a little bit more the memory cache.
Sessions InProc vs. In Cache
I prefer to use the memory cache as much as I can as it is faster than going to the SQL Server every time I need a piece of information. Now I am sure you are thinking, just use Sessions InProc. Well, I am trying to avoid that as much as I can. Why? If you have used InProc, you can answer this question in a sentence. If you want to store Sessions on your SQL Server there is a reason for that (Web Farms or Web Gardens).
Cache does not work with Web Farms
I know! However if used with SQL Server, it makes it a little bit more interesting and fast. To retrieve the Session we will first check if there is a copy on the local cache, if not we will have to go to the SQL Server.
Let's write Code!
using System;
Session["Test"] = "Storing a string";
string sTemp = Session["Test"];
So now let's do it with Cache:
AlsUtils.BetterSession pSession = new BetterSession();
pSession["test"] = "hello";
pSession["bye"] = "Good Bye";
string sTemp = pSession["test"];
string sTemp2 = pSession["bye"];
pSession.ClearSession();
The simple class that makes everything possible:
using System;
using System.Collections;
namespace AlsUtils
{
public class BetterSession : DictionaryBase
{
public object this[string key]
{
get
{
if (System.Web.HttpContext.Current.Cache[
System.Web.HttpContext.Current.Session.SessionID +
"~" + key] != null )
return(System.Web.HttpContext.Current.Cache[
System.Web.HttpContext.Current.Session.SessionID
+ "~" + key]);
else if (System.Web.HttpContext.Current.Session[key] != null )
{
System.Web.HttpContext.Current.Cache[
System.Web.HttpContext.Current.Session.SessionID
+ "~" + key] =
System.Web.HttpContext.Current.Session[key];
Add(System.Web.HttpContext.Current.Session.SessionID
+ "~" + key, System.Web.HttpContext.Current.Cache[
System.Web.HttpContext.Current.Session.SessionID
+ "~" + key]);
return(System.Web.HttpContext.Current.Session[key]);
}
return (null);
}
set
{
System.Web.HttpContext.Current.Cache[
System.Web.HttpContext.Current.Session.SessionID
+ "~" + key] = value;
System.Web.HttpContext.Current.Session[key] = value;
Add(System.Web.HttpContext.Current.Session.SessionID
+ "~" + key, value);
}
}
public void ClearSession()
{
string sSessionID =
System.Web.HttpContext.Current.Session.SessionID;
ArrayList pArray = new ArrayList(Keys);
for ( int i=0; i<pArray.Count; i++)
{
if ( pArray[i].ToString().IndexOf(sSessionID+"~") == 0)
System.Web.HttpContext.Current.Cache.Remove(
pArray[i].ToString());
}
}
protected void Add(string key, object oValue)
{
this.Dictionary.Add(key, oValue);
}
protected bool Contains(string key)
{
return this.Dictionary.Contains(key);
}
protected ICollection Keys
{
get {return this.Dictionary.Keys;}
}
}
}
Conclusion
Well this is the idea. There is something pretty important to remember, the cache does not have time limit, so if you want the Cache to destroy itself in 30 minutes, you'll have to change the line that adds that to:
System.Web.HttpContext.Current.Cache.Insert(sSessionID+"~"+key,
value, null, System.Web.Caching.Cache.NoAbsoluteExpiration,
TimeSpan.FromMinutes(30));
If your application sets all the Sessions in the beginning and then you use Session to read the configuration for that user, this simple class will save you lots of round trips to the SQL Session database.
Hope this helps some people.