最近一个项目要用到.Net,用久了Hibernate直接用ADO.NET手写SQL的话真还有点不适应,还好NHibernate提供了对.Net的ORM支持。在使用Hibernate的时候

,可以使用ThreadLoca来存放Session的。ThreadLoca是给每个线程提供单独的静态变量,在一个线程内部共享,而不同的线程间不共享。在.Net中找了好长时间

,终于找到了ThreadStaticAttribute ,它指示静态字段的值对于每个线程都是唯一的。在WinFrom,控制台应用程序和类库等中的确是可以用的。但在Asp.Net中

HttpRequest则可能有多个线程为其服务。如果用ThreadStaticAttribute 的话,很有可能同一个请求使用多个线程那么数据就不能共享了。不过我们可以使用

HttpContext.Current.Items来存放session。所以就自己写一个等同ThreadLocal的类来存放Session,代码如下:

    /// <summary>
    
/// 在.NET应用程序中,为一个单线程
    
/// 在ASP.NET应用程序中,为一个请求
    
/// </summary>
    
/// <author>Kevin</author>

    public class SessionHolder
    
{
        
private HolderSupport holderSupport;

        
public SessionHolder()
        
{
            
if (HttpContext.Current != null)
            
{
                holderSupport 
= new AspNetHolderSupport();
            }

            
else
            
{
                holderSupport 
= new NetHolderSupport();
            }

        }


        
public ISession Get()
        
{
            
return holderSupport.Get();
        }


        
public void Set(ISession session)
        
{
            holderSupport.Set(session);
        }


        
class NetHolderSupport : HolderSupport
        
{
            [ThreadStatic]
            
private static ISession threadLocal;

            
public ISession Get()
            
{
                
if (threadLocal != null)
                
{
                    
if (!threadLocal.IsConnected)
                    
{
                        threadLocal.Reconnect();
                    }

                }


                
return threadLocal;
            }


            
public void Set(ISession session)
            
{
                
if (session == null)
                
{
                    threadLocal 
= null;
                    
return;
                }


                
if (!session.IsConnected)
                
{
                    session.Reconnect();
                }


                threadLocal 
= session;
            }

        }


        
class AspNetHolderSupport:HolderSupport
        
{
            
private readonly object DEFAULT_SESSION_KEY = new object();

            
public ISession Get()
            
{
                
return HttpContext.Current.Items[DEFAULT_SESSION_KEY] as ISession;
            }


            
public void Set(ISession session)
            
{
                
if (session != null)
                
{
                    HttpContext.Current.Items.Add(DEFAULT_SESSION_KEY, session);
                }

                
else
                
{
                    HttpContext.Current.Items.Remove(DEFAULT_SESSION_KEY);
                }

            }

        }


        
interface HolderSupport
        
{
            ISession Get();
            
void Set(ISession session);
        }

    }


 

    自己又写了一个SessionFactoryUtil类,用来打开和关闭Session,代码如下:
   

public abstract class SessionFactoryUtil
    
{
        
private static readonly object lockObj = new object();
 
        
private static ISessionFactory factory;

        
private static readonly SessionHolder holder = new SessionHolder(); 

        
public static ISessionFactory Factory
        
{
            
get
            
{
                
if (factory == null)
                
{
                    
lock (lockObj)
                    
{
                        
if (factory == null)
                        
{
                            Configuration cfg 
= new Configuration();
                            cfg.AddAssembly(Assembly.GetExecutingAssembly());
                            factory 
= cfg.BuildSessionFactory();
                        }

                    }

                }


                
return factory;
            }

        }


        
public static ISession CurrentSession()
        
{
            ISession session 
= holder.Get();

            
if (session == null)
            
{
                session 
= Factory.OpenSession();
                holder.Set(session);
            }


            
return session;
        }


        
public static void CloseSession()
        
{
            ISession session 
= holder.Get();

            
if (session != null)
            
{
                session.Close();                
            }


            holder.Set(
null);
        }

    }