在Web应用程序中使用Autofac管理NHibernate事务的最佳方法是什么?
我的会话方法是
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession())
.ContainerScoped();
对于ITransaction
,我在Google代码上有found an example,但在决定是否回滚时依赖于HttpContext.Current.Error
。
有更好的解决方案吗? NHibernate交易应该的范围是什么?
答案 0 :(得分:4)
我刚刚发布了这个:
已修改,因此拦截器具有日志记录功能,[Transaction]属性也可用于类。
[global::System.AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TransactionAttribute : Attribute
{
}
public class ServicesInterceptor : Castle.Core.Interceptor.IInterceptor
{
private readonly ISession db;
private ITransaction transaction = null;
public ServicesInterceptor(ISession db)
{
this.db = db;
}
public void Intercept(IInvocation invocation)
{
ILog log = LogManager.GetLogger(string.Format("{0}.{1}", invocation.Method.DeclaringType.FullName, invocation.Method.Name));
bool isTransactional = IsTransactional(invocation.Method);
bool iAmTheFirst = false;
if (transaction == null && isTransactional)
{
transaction = db.BeginTransaction();
iAmTheFirst = true;
}
try
{
invocation.Proceed();
if (iAmTheFirst)
{
iAmTheFirst = false;
transaction.Commit();
transaction = null;
}
}
catch (Exception ex)
{
if (iAmTheFirst)
{
iAmTheFirst = false;
transaction.Rollback();
db.Clear();
transaction = null;
}
log.Error(ex);
throw ex;
}
}
private bool IsTransactional(MethodInfo mi)
{
var atrClass = mi.DeclaringType.GetCustomAttributes(false);
foreach (var a in atrClass)
if (a is TransactionAttribute)
return true;
var atrMethod = mi.GetCustomAttributes(false);
foreach (var a in atrMethod)
if (a is TransactionAttribute)
return true;
return false;
}
}
答案 1 :(得分:4)
当我使用autofac时,我使用相同的容器范围方法,但不是将同一个会话传递给我的Repository / DAO对象,而是传递一个容器作用域的UnitOfWork。工作单元在构造函数中具有此功能。
private readonly ISession _session;
private ITransaction _transaction;
public UnitOfWork(ISession session)
{
_session = session;
_transaction = session.BeginTransaction();
}
处理是:
public void Dispose()
{
try
{
if (_transaction != null &&
!_transaction.WasCommitted &&
!_transaction.WasRolledBack)
_transaction.Commit();
_transaction = null;
}
catch (Exception)
{
Rollback();
throw;
}
}
我(ab)在autofac中使用确定性处理的东西来管理它,我有点喜欢它。
另一件事是我基本上只针对ASPNet环境,并有意识地决定事务是否与Web请求相关联。所以每个Web请求模式都有一个事务。
因为我可以在IHttpModule中执行此错误处理代码:
void context_Error(object sender, System.EventArgs e)
{
_containerProvider.RequestContainer.Resolve<IUnitOfWork>().Rollback();
}
我没有看过NHibernate.Burrow太近了,但我确信那里有大部分内容。
答案 2 :(得分:-1)
我通常自己管理交易..
public ActionResult Edit(Question q){
try {
using (var t = repo.BeginTransaction()){
repo.Save(q);
t.Commit();
return View();
}
catch (Exception e){
...
}
}