在使用Ninject管理会话的请求期间发生异常时,如何回滚nHibernate事务? [英] How to rollback nHibernate transaction when an exception occurs during request having Ninject for managing sessions?
问题描述
我将nHibernate用于ORM,将Ninject用于IoC. 我为每个自定义范围创建nHibernate会话(您可以假定是针对每个请求). 我开始交易onActivation. 我在onDeactivation上提交了交易.
I use nHibernate for ORM and Ninject for IoC. I create nHibernate sessions per some custom scope (which you can assume is per request). I begin the transaction onActivation. I commit the transaction onDeactivation.
问题是,如果请求期间发生异常,我想回滚事务而不是提交事务.知道如何检测(以一种干净的方式,最有可能使用Ninject Context)异常发生了吗?
The problem is that if an exception happens during the request I want to rollback the transaction rather than committing it. Any idea how to detect (in a clean way, most probably using Ninject Context) that an exception has happened?
注意:我并不担心提交时可能发生的异常,这些异常可以很容易地捕获到以下代码中,并且可以轻松地返回角色.
Note: I am not concerned about the exceptions that can happen on commit which I can catch in the following code and role back easily.
protected void BindWithSessionWrapper<T>(Func<IContext, T> creationFunc) where T : ISessionWrapper
{
Bind<T>().ToMethod(creationFunc)
.InScope(x => new NinjectCustomScope()) // work in progress !!!
.OnActivation(t => t.Session.BeginTransaction(IsolationLevel.ReadCommitted))
.OnDeactivation((c, t) =>
{
t.Session.Transaction.Commit();
t.Session.Dispose();
});
}
更新:
我遵循了@BatteryBackupUnit的建议. 因此,我将以下内容添加到错误EventHandler中:
I followed the suggestion by @BatteryBackupUnit. So I added the following to the Error EventHandler:
Error += (s, e) =>
{
HttpContext.Current.Items["ErrorRaised"] = true;
};
然后我将OnDeactivation修改如下:
And I modified the OnDeactivation to look like this:
OnDeactivation(t =>
{
if ((bool?)HttpContext.Current.Items["ErrorRaised"] == true)
t.Session.Transaction.Rollback();
else
t.Session.Transaction.Commit();
t.Session.Dispose();
});
它可以正常工作,但是如果Ninject会在发生异常的情况下在Context中设置一个标志来解决这一问题,那将更好:)
It works fine, but that would be better if Ninject would take care of this by setting a flag in the Context if an exception happened :)
推荐答案
如何实现IHTTPModule
并订阅Error
事件?
如此处
How about implementing an IHTTPModule
and subscribing to the Error
event?
Like described here
在Error
事件处理程序中,使用System.Web.Mvc.DependencyResolver.Current.GetService(typeof (ISession))
检索当前会话并回滚事务.
In the Error
event handler, use System.Web.Mvc.DependencyResolver.Current.GetService(typeof (ISession))
to retrieve the current session and rollback the transaction.
但是请注意,如果请求不使用会话,则会创建一个会话,这是多余的.
Note, however, that in case the request did not use a session, this will create one, which is quite superfluous.
您可能会执行类似检查事务是否已开始然后才回滚的操作.但是您仍然会不必要地创建会话.
You might do something like checking whether a transaction was started and only then rolling it back. But you'd still create a session unnecessarily.
您可以通过使用Error
事件处理程序在HttpContext.Current.Items
上设置标志来进一步改善该效果,例如
You could further improve that by using the Error
event handler to set a flag on HttpContext.Current.Items
, like
HttpContext.Current.Items["RollbackTransaction"] = true;
,然后在会话的OnDeactivation
中使用它,例如:
and then use it in the OnDeactivation
of the session like:
.OnDeactivation((c, t) =>
{
if(HttpContext.Current.Items.Contains("RollbackTransaction"])
{
t.Session.Transaction.Rollback();
}
else
{
t.Session.Transaction.Commit();
}
t.Session.Dispose();
});
请注意,HttpContext
是线程本地的,这意味着当您切换线程时,它可能是null
或-最坏的情况-甚至可能是另一个HttpContext
.
Please note that HttpContext
is thread local, that means when you switch threads it may be null
or -worst case - it might even be another HttpContext
.
还请注意,我无法尝试它,因此它可能无法正常工作.反馈表示赞赏.
Please also note that i was unable to try it out so it may not work. Feedback appreciated.
这篇关于在使用Ninject管理会话的请求期间发生异常时,如何回滚nHibernate事务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!