Storing LINQ Objects in SQL-Based Session State

Scott Hanselman recently posted about various options you have for session storage while using ASP.Net. In the comments of his post I brough up an issue I recently encountered at work (where we use SQL Server session state):

LINQ-To-Sql generated objects are not marked [Serializable] and cannot be stored in out-of-process session storage.

To get around this I have whipped up the following helper class which will serialize LINQ-To-Sql objects if you set the DataContext's Serializable property to "Unidirectional".

Note: The following class does not current work for storing List<X> where X is a LINQ-To-Sql object. I'll be working to resolve that sometime later this week.

   1: using System;
   2: using System.IO;
   3: using System.Runtime.Serialization;
   4: using System.Text;
   5: using System.Xml;
   6: using System.Web;
   7:  
   8: namespace SquaredRoot.Helper
   9: {
  10:   public class SessionHelper
  11:   {
  12:  
  13:     private SessionHelper(){}
  14:  
  15:         public static T Get<T>( string key ) where T : class
  16:         {
  17:  
  18:             object o = HttpContext.Current.Session[key];
  19:             if( o == null )
  20:                 return default( T );
  21:  
  22:             if( o.GetType() == typeof( string ) && typeof( T ) != typeof( string ) )
  23:             {
  24:                 string s = o as string;
  25:                 Stream stream = new MemoryStream( Encoding.Unicode.GetBytes(s) );
  26:                 XmlDictionaryReader xml = XmlDictionaryReader.CreateTextReader( stream, new XmlDictionaryReaderQuotas() );
  27:                 DataContractSerializer dcs = new DataContractSerializer( typeof( T ) );
  28:                 T t = (T)dcs.ReadObject( xml, true );
  29:                 xml.Close();
  30:                 return t;
  31:             }
  32:             else
  33:                 return o as T;
  34:  
  35:         }
  36:  
  37:         private static bool HasClassAttribute( object o, Type attribute, bool inherit )
  38:         {
  39:             return ( o.GetType().GetCustomAttributes( attribute, inherit ).Length > 0 );
  40:         }
  41:  
  42:         public static void Set( string key, object item )
  43:         {
  44:  
  45:             object value = item;
  46:             if( HasClassAttribute( item, typeof(DataContractAttribute), false )
  47:         && !HasClassAttribute( item, typeof(SerializableAttribute), false ) )
  48:             {
  49:                 DataContractSerializer dcs = new DataContractSerializer(item.GetType());
  50:                 StringBuilder sb = new StringBuilder();
  51:                 XmlWriter writer = XmlWriter.Create(sb);
  52:                 dcs.WriteObject( writer, item );
  53:                 writer.Close();
  54:                 value = sb.ToString();
  55:             }
  56:  
  57:             if( HttpContext.Current.Session[key] == null )
  58:         HttpContext.Current.Session.Add( key, value );
  59:             else
  60:         HttpContext.Current.Session[key] = value;
  61:  
  62:         }
  63:  
  64:     }
  65: }