2017-05-29 87 views
1

我有一個WebAPI項目,並且正在將我的exception捕獲從try/catch捕獲到exceptionfilters。以前當我用try/catch塊我能夠訪問SQL命令對象來獲取SQL命令文本記錄到數據庫中。現在我轉移到異常過濾器,我不再能夠訪問SQL命令對象。我所追求的是將上一次執行的SQL命令傳遞給異常過濾器的方式,以便我仍然可以記錄它。傳遞值給ExceptionFilter

以前的代碼(try/catch塊)

public HttpResponseMessage API([FromBody] int roomID) 
{ 
    HttpResponseMessage msg = null; 
    SqlCommand comm = Common.Shared.ConnectDB(); 

    try 
    { 
     List<Models.room> room = room(comm, roomID); 
     msg = Request.CreateResponse(HttpStatusCode.OK, room); 
    } 
    catch (CustomException ex) 
    { 
     msg = Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message); 
    } 
    catch (Exception ex) 
    { 
     comm.Parameters.Clear(); 
     var sourceFunction = "rooms"; 
     var returnException = Common.Logging.CreateLog(ex, comm, sourceFunction); 
     msg = Request.CreateResponse(HttpStatusCode.InternalServerError, returnException); 
    } 
    finally 
    { 
     comm.Connection.Close(); 
    } 
    return msg; 
} 

異常過濾器代碼

public class InternalServerErrorFilter : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    { 
     Log.Error(context.Exception, "Exception Information"); 

     context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError); 
    } 
} 

控制器異常過濾器

[InternalServerErrorFilter] 
[HttpPost] 
public HttpResponseMessage API([FromBody] int roomID) 
{ 
    HttpResponseMessage msg = null; 
    SqlCommand comm = Common.Shared.ConnectDB(); 

    try 
    { 
     List<Models.room> room = room(comm, roomID); 
     msg = Request.CreateResponse(HttpStatusCode.OK, room); 
    } 
    finally 
    { 
     comm.Connection.Close(); 
    } 
    return msg; 
} 

回答

1

有幾個方法,你可以處理這種場景:

檢查和投Exception型爲更具體的例外,像SqlException(檢查documentation)。在SqlException內部,您可以找到該例外的原因。

public class InternalServerErrorFilter : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    { 
     if (context.Exception is SqlException) 
     { 
      var sqlException = (SqlException)context.Exception; 
      //Do your logging... 
     } 
     context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError); 
    } 
} 

或者你可以創建自定義的SQL異常,對此你會通過你的SqlCommand進一步的記錄。但是,您需要檢查類型(如上所述)才能獲得強類型訪問。

public class CustomSqlException : Exception 
{ 
    public SqlCommand ExecutedCommand { get; } 

    public CustomException(SqlCommand executedCommand) 
     : base("Custom Message") 
    { 
     ExecutedCommand = executedCommand; 
    } 
} 

public class InternalServerErrorFilter : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    { 
     if (context.Exception is CustomSqlException) 
     { 
      var sqlException = (CustomSqlException)context.Exception; 
      var command = sqlException.ExecutedCommand; 
      //Do your logging... 
     } 
     context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError); 
    } 
} 

用法:

[InternalServerErrorFilter] 
    [HttpPost] 
    public HttpResponseMessage API([FromBody] int roomID) 
    { 
     HttpResponseMessage msg = null; 
     SqlCommand comm = Common.Shared.ConnectDB(); 

     try 
     { 
      List<Models.room> room = room(comm, roomID); 
      msg = Request.CreateResponse(HttpStatusCode.OK, room); 
     } 
     catch (SqlException ex) 
     { 
      throw new CustomSqlException(comm); 
     } 
     finally 
     { 
      comm.Connection.Close(); 
     } 
     return msg; 
    } 

我會建議你使用第一種方法,因爲SqlException有關於誤差而SQL服務器上執行SQL命令其內容時發生的所有必要信息。除此之外,由於拋出新的異常,您不會丟失堆棧跟蹤。

如果你決定使用第二種方案,你可以規避傳遞例外,因爲你CustomSqlException的內部異常失去堆棧跟蹤的問題。

+0

這將適用於SQL異常。不過我也希望能搶SQL命令其他異常,如由數據讀取器等,這些不亂扔SQL異常,因此我不會得到其使用的數據讀取器等 – Nathan

+0

命令字符串拋出@Nathan,那麼你可以選擇第二個選項。但是,您需要手動處理由數據讀取器引發的異常。你不必捕獲'SqlException',你可以捕獲'Exception'。 –