[Update: fixed a couple of syntactic bugs that Luke Hutteman was kind enough to point out. Not sure why, but DasBlog's mail-to-weblog feature likes to eat underscores. Wish I could say that it likes to eat downcasts, too, but that one's my fault]
I’ve seen this pattern a lot in ASP.NET applications:
//Inside some function…
newOrder.CreditCard = (CreditCardInfo)HttpContext.Current.Session[CREDITCARD_KEY];
newOrder.BillingAddress = (AddressInfo)HttpContext.Current.Session[BILLING_KEY];
newOrder.ShippingAddress = (AddressInfo)HttpContext.Current.Session[SHIPPING_KEY];
That is, using Session state as this big unorganized mess of keys and values seems to be pretty pervasive. Sure it works, but the problem is that it’s slow. At least it’s not as fast as it could be. All that downcasting is expensive, and all those hash lookups add up. Why make your system do all that unnecessary work when it doesn’t have to?
A better way is to do this involves giving some structure to Session. Instead of sticking all your data in a loosely-typed hashtable type thing, create a strongly typed container to hold your data and stick a single instance of that class in Session under a well-known key. A sample class that would cover the lines of code above would look like this:
public class SessionDataContainer
{
public SessionStore()
{
}
public CreditCardInfo CREDITCARD;
public BillingAddress BILLING;
public ShippingAddress SHIPPING;
}
Inside of the Session Start() event handler inside global.asax, initialize a single instance of SessionDataContainer by doing the following:
protected void Session_Start(Object sender, EventArgs e)
{
Session[ CONTAINER_KEY ] = new SessionDataContainer();
}
This would allow the code shown above to be rewritten as follows:
SessionDataContainer sessionState =
(SessionDataContainer)HttpContext.Current.Session[ CONTAINER KEY ];
newOrder.CreditCard = sessionState.CREDITCARD;
newOrder.BillingAddress = sessionState.BILLING;
newOrder.ShippingAddress = sessionState.SHIPPING;
This replaces n downcasts and n hash lookups with 1 downcast and 1 hash lookup. Plus, it has the additional advantage of being type-checked at compile time and therefore less prone to bugs. Clearly the biggest payoff comes when n (the number of unique session keys being accessed) is significantly larger than 1, but there are performance gains to be seen from n as small as 2 -- and the compile-time type checking is just icing on the cake.
