事务异常问题 - s#arp体系结构

时间:2010-07-06 11:31:49

标签: asp.net-mvc s#arp-architecture

我正在删除这样的内容:

[Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult DeleteQualitativeGlobalFeatureValue(string Id)
        {
            try
            {
                BlaService.DeleteBla(Id);
            }
            catch (Exception e)
            {
                ModelState.AddModelError("Exception", e.Message);
            }

            return RedirectToAction("Bladibla", new { Id = FeatureId });
        }

但是,如果某些内容被“非法”删除(例如导致违反引用约束),我会收到一个可怕的异常,而这个异常并不会被我的try catch块捕获。我认为这与[Transaction]属性有关。如何避免这种情况在控制器方法中捕获任何异常?

感谢。

祝福,

基督教

2 个答案:

答案 0 :(得分:1)

这是因为实际提交和数据库端验证在事务提交时发生。

您可以使用自己的,稍微修改过的Sharp属性版本。

public class TransactionAttribute: ActionFilterAttribute
{
  private TransactionAttributeHelper helper = new TransactionAttributeHelper();
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     helper.BeginTransaction();
  }

  public override void OnActionExecuted(ActionExecutedContext filterContext)
  {
     try
     {
        // notice that I rollback both on exception and model error, this helps a lot
        helper.FinishTransaction(filterContext.Exception == null &&
                                 filterContext.Controller.ViewData.ModelState.IsValid);
     }
     catch (Exception ex)
     {
        // here add ModelError, return error, or redirect
     }
  }
}

TransactionAttributeHelper放置在.Data程序集中以避免.Controllers中的NHibernate引用。

public class TransactionAttributeHelper
{
  public void BeginTransaction()
  {
     NHibernateSession.CurrentFor(GetEffectiveFactoryKey()).BeginTransaction();
  }

  public void FinishTransaction(bool commit)
  {
     string effectiveFactoryKey = GetEffectiveFactoryKey();

     ITransaction currentTransaction =
         NHibernateSession.CurrentFor(effectiveFactoryKey).Transaction;

     if (currentTransaction.IsActive)
     {
        if (commit)
        {
           currentTransaction.Commit();
        }
        else
        {
           currentTransaction.Rollback();
        }
     }
  }

  private static string GetEffectiveFactoryKey()
  {
     return NHibernateSession.DefaultFactoryKey;
  }
}

或者,当然,您可以使用repository.DbContext.BeginTransaction / Commit / etc方法进行不带属性的转换,并手动捕获/处理错误。但是上述方法可以避免许多这样的手工工作。

答案 1 :(得分:0)

您应该查看实现IExceptionFilter接口的属性。例如,System.Web.Mvc.HandleErrorAttribute可以显示异常的备用视图,并为该视图提供对异常的访问权限。如果要以不同方式处理事物或使用log4net或Elmah记录异常,您还可以创建自己的实现IExceptionFilter的属性。

即使在TransactionAttribute的代码中发生异常,在方法上使用IExceptionFilter属性也会捕获异常。