In the StructureMap documentation on life cycle they state that one scoping option is HttpSession and that it: "Caches the instances in the HttpContext.Session collection. Use with caution."
I don't know what to be cautious of and my google-fu is failing me.
The use-case we have is that we have some expensive web service calls we'd like to cache. Some of which are stateless but some of which are tied to a particular user.
When are we bad, naughty people if we inject in Session scope? What do we need to guard against?
I'll describe the problems with this by using an extreme example, caching a Unit of work object (such as LINQ to SQL's DataContext
, Entity Framework's ObjectContext
or DbContext
or NHibernate's ISession
):
Memory footprint
Unit of work objects often hold on to a large amount of objects. Putting the session object in a HttpSession means that it will live for as long as the session lives and with it all the objects that are in cache. Even if the user comes back after 20 minutes, you will have this memory pressure on your application. This can (and under considerable load will) result in out of memory exceptions.
Data becomes stale
Since the unit of work object caches all entities that it loaded from the database, that data becomes stale rather quickly. When the data get changed by another user, cached data won't be refreshed by default, and you can experience weird behavior where one user sees some data, but another user sees other data. Refreshing the page won't work, since you cached the data for the lifetime of the session. Only closing the browser will work (sometimes).
Serialization
When you're scaling your web server out (which means you add more servers) session information must be transported from one server to the other. You will have to use an out-of-process cache (such as MemCache or SQL Server). Unit of work object are difficult or impossible to serialize and deserialize, meaning that you can't scale out if you want or need to.
Summary
The example is extreme, because you should never use a per session lifestyle on unit of work pattern. But it still describes the problem fairly clear. The per session lifestyle increases the memory footprint of your application, since the service is kept alive very long. If you use such service to cache data, it can become stale (although the cache might just be what you need to improve performance). Although DTOs are often easy to serialize, this doesn't hold for any service you register. This means that you can't scale out, since serializable session objects are required to scale out.
So instead of using a Per Session lifestyle on services, try building services that are stateless so that they can be registered as singleton. Any user specific data they need can be requested from the the HTTP session.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With