这是我今天遇到的另一个奇怪的问题!!!我使用nhibernate创建了MVC 4应用程序。并在我的HomeController上添加了一个名为[LoggingNHibernateSessionAttribute]的过滤器属性,用于管理每个操作的会话。我遵循了'ASP.NET MVC4和Apress发布的Web API'。
public class LoggingNHibernateSessionAttribute : ActionFilterAttribute
{
private readonly IActionLogHelper _actionLogHelper;
private readonly IActionExceptionHandler _actionExceptionHandler;
private readonly IActionTransactionHelper _actionTransactionHelper;
public LoggingNHibernateSessionAttribute()
: this(WebContainerManager.Get<IActionLogHelper>(),
WebContainerManager.Get<IActionExceptionHandler>(),
WebContainerManager.Get<IActionTransactionHelper>())
{
}
public LoggingNHibernateSessionAttribute(
IActionLogHelper actionLogHelper,
IActionExceptionHandler actionExceptionHandler,
IActionTransactionHelper actionTransactionHelper)
{
_actionLogHelper = actionLogHelper;
_actionExceptionHandler = actionExceptionHandler;
_actionTransactionHelper = actionTransactionHelper;
}
public override void OnActionExecuting(ActionExecutingContext actionExectingContext)
{
_actionLogHelper.LogEntry(actionExectingContext.ActionDescriptor);
_actionTransactionHelper.BeginTransaction();
}
public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
{
_actionTransactionHelper.EndTransaction(actionExecutedContext);
_actionTransactionHelper.CloseSession();
_actionExceptionHandler.HandleException(actionExecutedContext);
_actionLogHelper.LogExit(actionExecutedContext.ActionDescriptor);
}
}
ActionTransactionHelper
public class ActionTransactionHelper : IActionTransactionHelper
{
private readonly ISessionFactory _sessionFactory;
private readonly ICurrentSessionContextAdapter _currentSessionContextAdapter;
public ActionTransactionHelper(
ISessionFactory sessionFactory,
ICurrentSessionContextAdapter currentSessionContextAdapter)
{
_sessionFactory = sessionFactory;
_currentSessionContextAdapter = currentSessionContextAdapter;
}
public void BeginTransaction()
{
var session = _sessionFactory.GetCurrentSession();
if (session != null)
{
session.BeginTransaction();
}
}
public bool TransactionHandled { get; private set; }
public void EndTransaction(ActionExecutedContext filterContext)
{
var session = _sessionFactory.GetCurrentSession();
if (session == null) return;
if (!session.Transaction.IsActive) return;
if (filterContext.Exception == null)
{
session.Flush();
session.Transaction.Commit();
}
else
{
session.Transaction.Rollback();
}
TransactionHandled = true;
}
public bool SessionClosed { get; private set; }
public void CloseSession()
{
if (_currentSessionContextAdapter.HasBind(_sessionFactory))
{
var session = _sessionFactory.GetCurrentSession();
session.Close();
session.Dispose();
_currentSessionContextAdapter.Unbind(_sessionFactory);
SessionClosed = true;
}
}
}
运行应用程序时,我可以在dataBase中保存实体。但是当我点击刷新按钮并且异常抛出指示会话关闭时。
我不知道为什么会这样。 (我搜索并找到了这个NHibernate throwing Session is closed,但无法解决我的问题。)
在我的NinjectConfigurator中,我在所有注射中添加了inRequestScope(),但没有回答。我查看刷新页面会话时会打开。但我不知道为什么说会议结束了?!
更新
当我第一次运行应用程序时我可以创建一个新成员。但是当我点击刷新按钮时,会话将意外关闭!! 第一次运行:
:
注意:但是当没有调用endTransaction和closeSession时。会议如何结束? 如果我在onActionExecute()中评论closeSession()。会话总是开放的,如果刷新页面,一切都很好。 我检查了很多,尝试了不同的方式。它只发生在第二次我想用我的customMembership进行CRUD操作时。
对于其他实体来说,它就像一个魅力! 我已经上传了我的示例代码。用于测试只是创建和清空数据库并更改连接字符串。然后转到localHost:***** / api / categories(用户和传递不需要)
下载示例项目: 大小:47 MB https://www.dropbox.com/s/o63wjng5f799fii/Hashem-MVC4ServicesBook.rar
大小:54 MB 邮编格式:https://www.dropbox.com/s/smrsbz4cbtznx1y/Hashem-MVC4ServicesBook2.zip
答案 0 :(得分:1)
这里非常重要的一点可能是NHibernate的本质。 NHibernate及其Session
在ASP.NET MVC中的寿命更长,可以预期。我的意思不仅仅是在
会话实际上也必须通过呈现的阶段生活。因为,我们可以在“Action()”中加载一些代理,但是它的集合只能在lazily
呈现期间加载View
。因此,即使在这些阶段,Session
必须打开(从请求开始的同一个会话)
其他的话...... 通过完整的请求保持会话开放。从授权开始,直到呈现内容。
注意:Anohter提示,只是为了确保一切正常,我正在使用这个场景(也许你也这样做):
Detail()
如果一切正常或Edit()
Update()
(它是POST方法)实际上,步骤 1。是其中一项操作Detail
或Edit
。在这种情况下,我们已经面临这个问题......
答案 1 :(得分:0)
您有此错误,因为 Asp.Net MVC不会为每个请求创建LoggingNHibernateSessionAttribute
的新实例。当您第一次请求操作然后使用此实例时,它会创建一个新实例未来的实例。
行为如下:
Post
- &gt;创建了“LoggingNHibernateSession”的新实例Put
- &gt;创建了另一个'LoggingNHibernateSession'实例Put
- &gt;使用上一步中的“LoggingNHibernateSession”实例首次调用Delete
- &gt;创建了另一个'LoggingNHibernateSession'实例
[LoggingNHibernateSession]
public JsonResult Post(Dto data)
{
/* ... */
}
[LoggingNHibernateSession]
public JsonResult Put(int id, Dto data)
{
/* ... */
}
[LoggingNHibernateSession]
public JsonResult Delete(int id)
{
/* ... */
}
可以使用构造函数中的Func<IActionLogHelper>
代替IActionLogHelper
来解决。 IActionLogHelper
的实例可以在OnActionExecuting
方法中初始化。
public class LoggingNHibernateSessionAttribute : ActionFilterAttribute
{
/* your code */
private readonly Func<IActionTransactionHelper> _getActionTransactionHelper;
private IActionTransactionHelper _actionTransactionHelper;
public LoggingNHibernateSessionAttribute()
: this(WebContainerManager.Get<IActionLogHelper>(),
WebContainerManager.Get<IActionExceptionHandler>(),
() => WebContainerManager.Get<IActionTransactionHelper>())
{
}
public LoggingNHibernateSessionAttribute(
IActionLogHelper actionLogHelper,
IActionExceptionHandler actionExceptionHandler,
Func<IActionTransactionHelper> getActionTransactionHelper)
{
_actionLogHelper = actionLogHelper;
_actionExceptionHandler = actionExceptionHandler;
_getActionTransactionHelper = getActionTransactionHelper;
_actionTransactionHelper = null;
}
public override void OnActionExecuting(ActionExecutingContext actionExectingContext)
{
_actionTransactionHelper = _getActionTransactionHelper();
_actionLogHelper.LogEntry(actionExectingContext.ActionDescriptor);
_actionTransactionHelper.BeginTransaction();
}
/* your code */
}