最近一个项目要用到.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);
}
}
/// 在.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);
}
}
{
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);
}
}