我在每个请求的asp.net会话中实现标准场景。 我的asp.net模块:
public class NHibernateSessionModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
void context_BeginRequest(object sender, EventArgs e)
{
var session = SessionManager.SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
}
void context_EndRequest(object sender, EventArgs e)
{
var session = SessionManager.CurrentSession;
if (session != null)
{
try
{
if (session.Transaction != null && session.Transaction.IsActive)
session.Transaction.Commit();
}
catch (Exception ex)
{
session.Transaction.Rollback();
throw new ApplicationException("Error committing database transaction", ex);
}
finally
{
session.Close();
}
}
CurrentSessionContext.Unbind(SessionManager.SessionFactory);
}
}
我的sessionManager是线程安全的单例:
public class SessionManager
{
private readonly ISessionFactory sessionFactory;
public static ISessionFactory SessionFactory
{
get { return Instance.sessionFactory; }
}
private ISessionFactory GetSessionFactory()
{
return sessionFactory;
}
public static ISession OpenSession()
{
return Instance.GetSessionFactory().OpenSession();
}
public static ISession CurrentSession
{
get
{
if (!CurrentSessionContext.HasBind(Instance.GetSessionFactory()))
return null;
return Instance.GetSessionFactory().GetCurrentSession();
}
}
public static SessionManager Instance
{
get
{
return NestedSessionManager.sessionManager;
}
}
private SessionManager()
{
Configuration configuration = new Configuration().Configure();
sessionFactory = configuration.BuildSessionFactory();
}
class NestedSessionManager
{
internal static readonly SessionManager sessionManager =
new SessionManager();
}
}
主要想法是在请求开始时打开会话,然后通过SessionManager.CurrentSession;
会话存储在配置的上下文中:
<property name="current_session_context_class">web</property>
我的存储库:
public class RepositoryNew<T> : BaseRepository<T>, IDisposable
{
public RepositoryNew()
{
if (NHibernateSession == null)
//Start session for not web version
}
public void Dispose()
{
//flush session for not web version
}
protected override sealed ISession NHibernateSession
{
get
{
return SessionManager.CurrentSession;
}
}
}
用法
protected void Page_Load(object sender, EventArgs e)
{
var repo = new RepositoryNew<Client>()
clients = repo.GetAll();
}
由于某种原因,此存储库不在模块中使用已打开的会话。
CurrentSessionContext.HasBind(Instance.GetSessionFactory())
返回false,因此我的代码在请求中启动第二个会话。 在调试器中,我看到我已经两次立即调试了SessionManager。 我有两个不同的ISesssion工厂。 我还没有想法什么是错的。我花了很多时间。
答案 0 :(得分:0)
在Http Begin Request中打开会话可能是另一回事,因为每个http请求都会像请求静态图像一样打开新会话,你必须改变这个策略,以便在每个Http请求中消除这个不必要的会话,你可以阅读这个博客并改变你的策略{{3 }}
答案 1 :(得分:0)
这是奇怪的错误。当我从项目中删除到SessionManager的链接时,它开始正常工作。