如何在没有代码重复的情况下处理事务?

时间:2012-06-05 14:24:03

标签: c# asp.net-mvc-3 transactions action-filter

每次我想在POST方法中使用事务时,我似乎都会重复自己。我可以使用动作过滤器吗?

[HttpPost]
public virtual ActionResult Create(CreateModel model)
{
  if (!ModelState.IsValid)
    return View(model);

  var instruction = new Instruction(CurrentUser);
  Mapper.Map(model, instruction);

  // how do I get rid of this?
  using (var uow = _unitOfWorkFactory.Create())
  {
    _repository.Save(instruction);

    uow.SaveChanges();
  }

  return RedirectToAction("Details", new {id = instruction.Id});
}

1 个答案:

答案 0 :(得分:1)

创建一个新的操作过滤器,在创建和使用UnitOfWork之前检查ModelStateHttpContext.Error属性:

public class TransactionalAttribute : ActionFilterAttribute
{
  private IUnitOfWork _unitOfWork;

  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    if (filterContext.Controller.ViewData.ModelState.IsValid && filterContext.HttpContext.Error == null)
      _unitOfWork = DependencyResolver.Current.GetService<IUnitOfWork>();

    base.OnActionExecuting(filterContext);
  }

  public override void OnActionExecuted(ActionExecutedContext filterContext)
  {
    if (filterContext.Controller.ViewData.ModelState.IsValid && filterContext.HttpContext.Error == null && _unitOfWork != null)
      _unitOfWork.SaveChanges();

    base.OnActionExecuted(filterContext);
  }
}

UnitOfWork的示例nhibernate实现(在IoC中注册):

public class NhibernateUnitOfWork : IUnitOfWork
{
  private readonly ISession _session;
  private ITransaction _transaction;

  public NhibernateUnitOfWork(ISession session)
  {
    _session = session;
    _transaction = session.BeginTransaction();
  }

  public void Dispose()
  {
    if (_transaction == null)
      return;

    if (!_transaction.WasCommitted)
      _transaction.Rollback();

    _transaction.Dispose();
    _transaction = null;
  }

  public void SaveChanges()
  {
    _transaction.Commit();
  }

}

用法:

[HttpPost, Transactional]
public virtual ActionResult Create(CreateModel model)
{
  if (!ModelState.IsValid)
    return View(model);

  var instruction = new Instruction(CurrentUser);
  Mapper.Map(model, instruction);
  _repository.Save(instruction);

  return RedirectToAction("Details", new {id = instruction.Id});
}

来源:http://blog.gauffin.org/2012/06/how-to-handle-transactions-in-asp-net-mvc3/