Проблема исключения транзакции - архитектура s # arp - PullRequest
0 голосов
/ 06 июля 2010

Я удаляю что-то вроде этого:

[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 });
        }

Однако, если что-то «незаконно» удалено (например, вызывает нарушение ссылочного ограничения), я получаю ужасное исключение, которое не попадает в мою попыткупоймать блок.Я предполагаю, что это связано с атрибутом [Transaction].Как я могу избежать этого, чтобы поймать ЛЮБЫЕ исключения в методе контроллера?

Спасибо.

С наилучшими пожеланиями,

Кристиан

Ответы [ 2 ]

1 голос
/ 06 июля 2010

Это связано с тем, что при фиксации транзакции происходит фактическое подтверждение и проверка на стороне базы данных.

Вы можете использовать собственную слегка модифицированную версию атрибута 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, чтобы избежать ссылки NHibernate в .Controllers.

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 и вручную обрабатывать ошибки / catch Но вышеупомянутый подход избавляет от такой ручной работы.

0 голосов
/ 06 июля 2010

Вы должны посмотреть на атрибут, который реализует интерфейс IExceptionFilter .Например, System.Web.Mvc.HandleErrorAttribute может отображать альтернативное представление для исключения и дает этому представлению доступ к исключению.Вы также можете создать свои собственные атрибуты, которые реализуют IExceptionFilter, если вы хотите обрабатывать вещи по-другому или регистрировать исключение с помощью log4net или Elmah .

Наличие атрибута IExceptionFilter в методе будет перехватывать исключение дажеесли исключение происходит в коде TransactionAttribute.

...