ASP.NET Cache and Session State Storage
Ok, I feel that I should have known this before, but until I tested this for myself today I wasn’t really sure and didn’t quite consider the implications.
Somebody on the Universal Thread asked about using the Cache object to store a DataSet and then reusing it. I replied not really thinking about this, saying that the DS gets serialized and then each new Cache request retrieves that instance from the serialized store.
Well, of course this is incorrect.
The Cache object lives inside the current AppDomain (ie. ASP.NET Application Scope) and it stores its entries in a Hashtable. When you store a reference object like a DataSet you are actually storing a live reference of that object, which means if you make a change to that object it’s reflected in all other clients that are trying to read that object or currently hold a reference.
The same is true with the Application object. With the Session object on the other hand it depends on how you store the object – InProc uses a live reference, but if you’re going to StateServer or SQLServer the reference is serialized:
|
Object |
Entry Storage |
|
Cache Object |
Live Reference |
|
Application Object |
Live Reference |
|
Session (InProc) |
Live Reference |
|
Session(StateServer/Sql Server) |
Serialized Reference |
What’s a bit surprising is that when I went looking for this information I couldn’t really dig up an entry that describes exactly what gets stored in the various State saving mechanisms. So I ran a very simple test using code like this:
// Put user code to initialize the page here
CacheItemTest T = this.Cache["Test"] as CacheItemTest;
if (T == null)
{
T = new CacheItemTest();
this.Cache["Test"] = T;
}
Response.Write("Cache: " + T.IntVal.ToString() + "<p>");
T.IntVal = T.IntVal +1;
where CacheItemTest is defined as:
public class CacheItemTest
{
public int IntVal = 0;
public string StrVal = "Rick";
public int Counter = 0;
}
If you run this you’ll see that the counter keeps going up on every request, which means that when we change the property we’re changing the live object that lives now both in our reference and a reference that the Cache object holds.
This has some fairly serious implications if you are updating data in this object. If you’re expecting that object to stay in a fixed state once pulled out of the Cache that will obviously not happen. This could also have implicit complications if you are dealing with an object stored that is not thread safe! For example, if you run some internal operation on an object that internally affects the state of the object by changing a field value this will affect the state of the object for the next caller or even one that already has a reference. For example, if there was some internal counter used to walk through a list and the counter was upped each time you went on to the next entry, and two requests did this at the same time the counter would get trashed and you’d get serious garbage. This is not a great example – after all that’s what iterators are for – but it gives you an idea.
It’s clear that Cache’d objects should be read only objects – unless you treat it like the multi-threaded and multi-referenced object that it actually is and handle synchronization properly. In this respect the Cache object behaves not much different than a pure static object reference. The advantage of Cache is that it handles object assignment synchronization so you’re guaranteed that an object gets created only once (which is a concern with statics in busy thread situations).
Session Object
It gets more interesting with the Session object. Consider this code adjusted for use with a Session object:
CacheItemTest TS = this.Session["Test"] as CacheItemTest;
if (TS == null)
{
TS = new CacheItemTest();
this.Session["Test"] = TS;
}
Response.Write("Session: " + TS.IntVal.ToString());
TS.IntVal = TS.IntVal +1;
With InProc Sessions the Cache object behaves as with the Cache object with an increasing counter: You’re pointing to a reference object that is returned to you from a Hashtable.
Now go into your web.config and change the operation to StateServer. The first thing that happens is that you get an error:
Unable to serialize the session state. Please note that non-serializable objects or MarshalByRef objects are not permitted when session state mode is 'StateServer' or 'SQLServer'.
What this means is that our type is not serializable so I have to add:
[Serializable]
to the type. Now it works…
I was actually surprised to see the behavior exactly the same as with InProc objects. Even though objects serialize ASP. Net tracks objects locally and writes out any changes out to the stateserver.
To see what’s happening I hooked up SQLServer Session state and fired up the SQL Monitor to watch what actually fires.
It appears that the Session object writes out the current Session, always, no matter whether you use it or not (assuming EnableSessionState is on on the page). There are no read operations once a session has been loaded once which means ASP.NET manages a copy in memory. But at the end of every hit the entire content of the session state gets dumped to the StateServer in what looks like binary serialization.
This means:
- You don’t have to write objects back to a session – it happens automatically
- Once you read an object it always gets written back whether you’ve touched it or not!
- You get all of the overhead of session serialization even if you don't use it or if you change a single value
Session["Test"] = TS;
when the Session entry exists already and this has basically no effect at all.
It’s pretty important to understand these things when dealing with state stores. Obviously it would be a pretty big problem if you have huge amounts of state in your Session object as you’re sending all of this to the Session store EVERY time on every page hit!
For InProc objects there’s obviously a hell of a lot less overhead, since it doesn’t have any of this serialization and storage overhead. For Cache objects you have to be aware of the fact that you’re dealing essentially with an object accessed across multiple threads, so make sure that you are only using thread-safe objects and you don’t write data to these objects unless you write the proper synchronization code.
The Voices of Reason
# re: ASP.NET Cache and Session State Storage
BOb
# re: ASP.NET Cache and Session State Storage
As to ReadOnly sessions, yes that makes sense. It's important to be explicit, but I bet that most pages that use sessions do both read and write operations.
It's just interesting that I have been stuck in the mode of 'serialization' when thinking about all of these objects rather than thinking of them as live object references that are not immutable and need to be explicitly updated.
It's very cool that this works the way it does and another one of those 'ASP.NET does things for you that you had to manuyally manage before'...
# re: ASP.NET Cache and Session State Storage
I have a gut feeling that the overhead involved in using SQL Server to manage session state storage nullifies the the advantages of having the web farm. Any rules of thumb on this, like you need at least n web servers to justify the performance hit of using SQL Server to manage session state?
Also, when SQL Server is being used to store session state, do you think it is better to use viewstate instead of session to persist small amounts of data?
Thanks in advance for any responses you may be inclined to offer.
# re: ASP.NET Cache and Session State Storage
Also look into State Service first - it is a bit more efficient than SQL Server - given SP1 of 1.1 I haven't seen any more problems like the one that started off this entry.
Remember also Web Farm is not all about performance either - scalability and redundancy are the key to a Web Farm by wideneing the incoming base for hits...
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
what type and where do you add that? thanks.
# re: ASP.NET Cache and Session State Storage
". now please tell me what should I do?
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
Does that mean that you can cache data in the application and the data will be stored in 3 places (assuming that there are 3 servers in a web farm?)
I was told by my friend that we might have some issues when we use caching in a load balancing environment since the cache will not be stored in all the servers. Hence thought of checking it. Any thoughts on this will be very helpful.
# re: ASP.NET Cache and Session State Storage
Yes Caching is machine specific at least in the out of the box solution. This means in a Web Farm each box will have a separate cache and in some instances this can cause problems if the Caches are out of sync. If one cache expires and refreshes before another you may see the content flipping back and forth which is not good...
There are third party solutions for cache implementations that use a database, but some of that defeats the purpose of caching in that there's some overhead.
Basically in a Web farm environment you have to think carefully about what to cache. If you have content that can cache but updates frequently then caching may not be a good choice. OTOH, if your cached content is mostly static and stays fairly constant then you're probably Ok.
# re: ASP.NET Cache and Session State Storage
# which is best Session or cache in asp.net
# re: ASP.NET Cache and Session State Storage
you need to give admin privileges on your sql server machine or machine on which state service is running for the user of the machine on which iis is running.
# re: ASP.NET Cache and Session State Storage
I have a scenerio in which i am saving a hashtable in state using session mode as SQLServer. The hashtable stores keys and values where key is is a serializable checkbox and value is some text. when i retrieve the hashtable from the state, the key property (checkbox checked property is set to true when it was false at the time of saving that into state) Due to this checkboxes are getting automatically selected in my page at the time of post back.
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
I faced a problem when I used the session object. I store a dataset in the session till the user saves the data to the db. Now this works fine for all users except for 2. When these 2 users login and navigate from base page to modal pop up's they loose the session information. I am sure the session is not expiring. Also when I checked what the session ID's were like (I logged them), it were diferrent for each response for these 2 users! For other users they are always the same. These two users are domain admins at our location. Any idea why this could happen?
Right now I switched to cache and wrote a custom sync code to maintain the cache info.
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
"Performance tips" people stress turning off Session Read and/or Write for each page whenever possible, and this explains why.
It also explains why my data still was updated even though I had forgot to specifically update the Session var myself.
Good stuff.
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
http://msdn.microsoft.com/msdnmag/issues/06/10/WickedCode/
Since the COM dll was created in VB 6, it is thread safe. Therefore I think my solution will not have any of the issues with thread synchronization you mention. Do you agree?
# re: ASP.NET Cache and Session State Storage
Could you brefiely explain any specific steps need to be taken to setup my web appln ready for load balancing
I have used form authentication,viewstate..... in my web site
# re: ASP.NET Cache and Session State Storage
I see that you have mentioned that the in-process nature of ASP.NET cache does pose problems in case of sessions. So true! In fact the in-process and standalone nature of ASP.NET isn't very scalable and reliable either. For more info on this please follow the link provided.
http://www.alachisoft.com/ncache/asp-net-cache.html
All the best!
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
check it out at http://www.sharedcache.com
# re: ASP.NET Cache and Session State Storage
Thanks
# re: ASP.NET Cache and Session State Storage
# re: ASP.NET Cache and Session State Storage
hey eic,
one way to do so is to use and additional API, NCache express, and use its Object Query Language(OQL) feature. I came accross this caching API when I was developing an OE tool for one of my clients.
When Icame across this blog, and after reading it till your post, I was convinced that all of us can use it according to our needs, from session caching to object caching, keeping data upto dated and getting the fresh data at any time using its write through and read through features. As it is a distributed caching solution, it gives us the capability to share data between and cache object.
you can get it from: http://www.alachisoft.com/download.html
# re: ASP.NET Cache and Session State Storage
I have a c# web page (3.5) with sessionState mode="StateServer".
I've also set the EnableSessionState="True" on the Page Directive of the page.
I load up a DataView object to a variable named "dv" and then try to save the dataview object to a session ... "Session["Source"] = dv" ...
and get the infamous error
"Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode."
StateServer service is running fine. I can save string variables or int variables (etc.), but I can't seem to save anything like an object or dataview, etc.
Can you advise why any object I try to save to session gives me this error? I have put the [Serializable] declaration on every class that exists (even the ones from the two other referenced projects in my solution, and still get the same error.
I got the same thing in another scneario trying to save a custom class (with [Serializable] declared on the class) to session ... Session["oContract"] = poContract.
I've tried everything I can find by googling.
Hopefully someone here can provide some insight.
Phillip
# re: ASP.NET Cache and Session State Storage
I have the same problems.
I use the 'SQLServer' mode to storage session.
But I am very sure that I don't put any unserialization object into session.
In the same program, it can work well in normal, but if some unknow trouble is happend
and get the infamous error
"Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode."
For solving this error, I must execute 'iisreset' and i don't have any idea about why the error happen.
Can you advise how to analyse the trouble?
James
# re: ASP.NET Cache and Session State Storage
You can also set the page session to ReadOnly. I forget how but this is supposed to be more performant. I have seen many optimizing ASP.Net app articles/session say this. If you make your page class default to this, and only change it to read/write on the pages that write/change session data.
Of course, if you are using InProc I can't see that there will be that much difference since it is just an inmemory reference.
BOb