13. November 2009 16:56
When using ASP.NET you can choose 4 different ways of storing session: In Process, State Server, SQL Server, or Custom. When using In Process the session is stored on the ASP.NET thread of the web server, but when using the State Server or SQL Server the sessions are stored outside the ASP.NET thread. When would you use Out of Process session state? Mostly when you have a web farm and you need to share the same session across all web servers. You might choose to use it even if you have one web server for the simple reason of saving memory on the web server.
When using In Process and you store an object in session, ASP.NET maintains the object in memory and holds a pointer to that object so it can be used on future requests. Based on this explanation you should be able to store almost any object in session, including LINQ to SQL Entities.
The problem arises when you use Out of Process Session State. Whether you use SQL Server or State Server the objects need to be serializable in order to be able to be persisted. The object graph of a LINQ to SQL entity can be very complex and you will need to make every single child entity and type serializable, which can become very cumbersome. I came up with a simple solution that is to serialize all objects when setting them in session and deserialize them when retrieving them from session. In order for this to work you have to make sure that your L2S entities are decorated with the DataContract attribute and the properties are also decorated with the DataMember attribute. If you generate your entities using SqlMetal then you can do so by using the /serialization:Unidirectional parameter or if you use the VS designer by right clicking on the design surface and specify “Uniderectional” in property grid for “Serialization Mode”.
Here are the helper methods:
1: public static MemoryStream Serialize<T>(T obj)
3: DataContractSerializer s = new DataContractSerializer(typeof(T));
4: MemoryStream ms = new MemoryStream();
5: s.WriteObject(ms, obj);
7: return ms;
10: public static T Deserialize<T>(MemoryStream ms)
12: DataContractSerializer s = new DataContractSerializer(typeof(T));
13: ms.Position = 0;
14: T retObject = (T)s.ReadObject(ms);
16: return retObject;
A sample on how to use them:
1: //Store in session
2: Session["User"] = Serialize(user);
4: //Retrieve from session
5: User user = Deserialize<User>(Session["User"] as MemoryStream);
Something to be aware of is that by serializing and deserializing a L2S entity you are detaching the entity from the datacontext and hence there will be no lazy loading of child objects nor insertions or updates of that entity. In other words the entity becomes a Plain Old CLR Object (POCO).