2012-06-05 45 views
0

我似乎每次重複我自己想要在我的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}); 
} 
+2

可以說你不應該直接在控制器寫入數據庫。因此IMO,這是執行這種抽象的錯誤地點/層。 (例如,在我的代碼中,我在WCF層執行) –

+0

我同意......除非它是一個快速而骯髒的實現 - 說一個原型 –

+0

@KirkWoll:在控制器中使用域模型和存儲庫在DDD中非常有效。我不使用混亂的對象,因爲我在這裏描述:http://blog.gauffin.org/2012/06/protect-your-data/ – jgauffin

回答

1

創建一個新的動作過濾器檢查ModelState和創建和使用的UnitOfWork前HttpContext.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); 
    } 
} 

樣本的NHibernate實現的UnitOfWork(在你的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/