我有一个使用 NHibernate 和 SQL Server 的 C# 后端的 ASP.Net 应用程序。
最近我注意到,在网络的某个页面上执行某些任务的时间很长,它会卡住并超时(NHibernate 异常)。
出现超时问题后,我转到 SQL Server Management Studio,我可以在监视器中看到如何有几十个没有任何状态的进程,并且都在同一个数据库中:
我到处搜索解决方案,但我不知道我是否可能错误地处理了 session 。这是我处理 session 的方式:
public static void DisposeSession()
{
FlushSession(true); // Method that does a commit if there is a transaction
ISession Session = CurrentSessionContext.Unbind(sessionFactory);
if (Session != null)
{
Session.Close();
Session.Dispose();
}
}
编辑 1:
我目前正在使用 WebForms,请求之间没有共享 session , session 正在正确处理。
问题是,当我开始遍历我的网络的不同部分(因此发出新请求)时,进程开始像图像中那样增长......并且在某个时刻,网页响应运行时错误或超时。
我如何控制这种行为? 是否可能每个请求只有一个进程,并在处理时关闭进程?
编辑 2:
我错了, session 管理是用第一个答案中提供的方法正确完成的。有进程,但它们由 NHibernate 正确管理。
最佳答案
首先,确保您的 CurrentSessionContext
不会在请求之间共享 session 。
通常这种上下文将 session 存储在 HttpContext.Current.Items
字典中。这是一个安全的地方,可确保它最终不会与其他 HTTP 请求共享。
相反,如果它在请求之间共享 session ,那么您的应用程序一旦承受负载就会对大多数用户失败。
如果它使用 ThreadContext
或 CallContext
,由于“ASP.Net thread agility”导致某些 http 请求切换线程和失去他们以前的 ThreadContext
和 CallContext
。 HttpContext.Current.Items
保证在 http 请求切换线程时保留,而不是其他线程。
如果此 CurrentSessionContext
看起来正确,则修复您的 DisposeSession
。它不能确保您的 session 在刷新失败的情况下关闭。
它应该更像是:
public static void DisposeSession()
{
try
{
FlushSession(true); // Method that does a commit if there is a transaction
}
finally
{
ISession Session = CurrentSessionContext.Unbind(sessionFactory);
if (Session != null)
{
// Dispose closes the session too. And Close dispose the transaction
// if there was one. And transaction Dispose rollbacks if it was pending.
Session.Dispose();
}
}
}
然后,检查此 DisposeSession
是否始终被调用,无论您的请求以何种方式结束。特别是检查触发异常的请求会发生什么。这包括一些使用 ThreadAbortException
的重定向情况,例如 Response.Redirect("...")
。
session 管理:
关于我通常使用的 session 管理模式,我将其绑定(bind)到依赖注入(inject),每个请求的生命周期和一个 http 模块确保无论请求的结果如何,事务都由 Action 过滤器 (MVC) 处理.
您的模式远非如此。如果您想更改它,您可能会更容易遵循此 blog post series来自一位 NHibernate 的老贡献者和 NHibernate 分析器的作者。
关于c# - SQL Server 的 NHibernate 超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42578270/