Jam*_*mes 3 c# nhibernate asp.net-mvc session-management session-per-request
我用NHibernate编写了一个C#MVC 3作为ORM,我在大多数页面加载时抛出了一些奇怪的异常.他们似乎主要涉及闭门会议等,我已经检查了大多数常见问题,但没有找到帮助.一些例外包括:
[[NHibernate.Util.ADOExceptionReporter]] : System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
[[NHibernate.Transaction.AdoTransaction]] : Begin transaction failed
System.Data.SqlClient.SqlException (0x80131904): The server failed to resume the transaction. Desc:3b00000006.
[[NHibernate.Transaction.AdoTransaction]] : Commit failed
System.NullReferenceException: Object reference not set to an instance of an object.
[[NHibernate.Transaction.AdoTransaction]] : Commit failed
System.Data.SqlClient.SqlException (0x80131904): The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
[[NHibernate.Util.ADOExceptionReporter]] : System.InvalidOperationException: The transaction is either not associated with the current connection or has been completed.
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
[[NHibernate.Transaction.AdoTransaction]] : Begin transaction failed
System.InvalidOperationException: SqlConnection does not support parallel transactions.
Run Code Online (Sandbox Code Playgroud)
我为异常的墙壁道歉,我怀疑它们是相关的,但代码中可能还有另一个错误,导致一两个错误.我不喜欢对这些东西使用随机字,但我似乎无法追踪调用它们的任何特定代码行,它们似乎只出现在与ISession对象相关的代码行中.我甚至在Global.asax文件中的BeginTranscation方法上抛出了"Session is closed"异常.
该应用程序在hibernate.cfg.xml中使用current_session_context_class的web选项.
我怀疑它与我的会话管理代码有关.该网站通常会同时加载大约10个AJAX请求,并且当多个页面同时加载时,错误似乎更频繁地发生.有两个会话工厂,每个工作数据库使用一个.
这是我的相关Global.asax代码:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
_sessionFactory = (new WebClientSessionManager()).MakeSessionFactory();
_sessionFactoryNotWeb = ClientSessionManager.MakeSessionFactory();
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
_session = _sessionFactory.OpenSession();
_sessionNotWeb = _sessionFactoryNotWeb.OpenSession();
CurrentSessionContext.Bind(_sessionNotWeb);
CurrentSessionContext.Bind(_session);
_session.BeginTransaction();
_sessionNotWeb.BeginTransaction();
}
protected void Application_EndRequest(object sender, EventArgs e)
{
//Same code is repeated for the _sessionFactoryNotWeb
ISession session = CurrentSessionContext.Unbind(_sessionFactory);
if (session != null)
{
if (session.Transaction.IsActive)
{
try
{
session.Transaction.Commit();
}
catch
{
session.Transaction.Rollback();
}
}
try
{
session.Dispose();
}
catch
{
}
}
Run Code Online (Sandbox Code Playgroud)
我看过NHibernate profiler中运行的页面.有时会话不是从BeginTranscation开始的,有时它们不是Committed,有时也不是; 而且最令人费解的是,有时他们会开始三次但没有完成.
通过此代码管理对ISession对象的任何调用(每个工厂都有一个):
public static ISession WebSession()
{
if (CurrentSessionContext.HasBind(MvcApplication._sessionFactory))
{
if (MvcApplication._sessionFactory.GetCurrentSession().IsOpen)
{
return MvcApplication._sessionFactory.GetCurrentSession();
}
else
{
log4net.LogManager.GetLogger(typeof(DBHandler)).Debug("Unbinding NHibernate session");
CurrentSessionContext.Unbind(MvcApplication._sessionFactory);
return WebSession();
}
}
else
{
log4net.LogManager.GetLogger(typeof(DBHandler)).Debug("Initialising NHibernate session");
var session = MvcApplication._sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
session.BeginTransaction();
return session;
}
}
Run Code Online (Sandbox Code Playgroud)
在整个应用程序中没有调用BeginTransaction或Commit,而不会刷新,提交,会话处理,然后根据上面的代码重新打开.你们可以在这方面散发的任何光芒都将非常感激!
您似乎将会话存储在Global.asax.cs中的全局(应用程序范围)属性中.这意味着,该属性包含创建的最后一个会话,而不是特定请求的会话.同时有两个请求,您甚至不知道您是否仍然访问刚刚创建的会话,因为它可能已经被下一个请求的另一个会话覆盖,运行相同的代码.如果要遵循每个请求的会话模式,则不应将会话存储在与Web请求无关的位置.例如,您可以将您的NH会话存储在HttpContext.Items-Collection中.作为MVC中会话管理的另一种方式,Ayende发布了一个关于如何围绕单个MVC动作而不是整个请求包装会话管理的一个很好的例子.
| 归档时间: |
|
| 查看次数: |
5471 次 |
| 最近记录: |