2013-06-05 43 views
1

我有幾個函數需要一個SQL查詢(已經添加了參數)並在數據庫上運行它。當SQL查詢失敗時,我想記錄完整的查詢,包括參數,以便準確查看導致失敗的原因。 query.ToString()返回IBM.Data.Informix.IfxCommand,所以目前我只是捕獲query.CommandText,但如果參數是什麼引起的問題,這並不能告訴我我正在處理的是什麼。記錄帶參數的參數化SQL查詢

這裏的查詢功能,我使用一個:

public DataTable CallDtQuery(IfxCommand query) 
{ 
    DataTable dt = new DataTable(); 
    using (IBM.Data.Informix.IfxConnection conn = new IfxConnection(sqlConnection)) 
    { 
    try 
    { 
     IBM.Data.Informix.IfxDataAdapter adapter = new IfxDataAdapter(); 
     query.Connection = conn; 
     conn.Open(); 
     adapter.SelectCommand = new IfxCommand("SET ISOLATION TO DIRTY READ", conn); 
     adapter.SelectCommand.ExecuteNonQuery(); //Tells the program to wait in case of a lock.  
     adapter.SelectCommand = query; 
     adapter.Fill(dt); 
     conn.Close(); 
     adapter.Dispose(); 
     } 
    catch (IBM.Data.Informix.IfxException ex) 
    { 
     LogError(ex, query.CommandText); 
     SendErrorEmail(ex, query.CommandText); 
     DisplayError(); 
    } 
    } 
    return dt; 
} 

這裏的記錄功能:

private void LogError(IfxException ex, string query) 
{ //Logs the error. 
    string filename = HttpContext.Current.Server.MapPath("~") + "/Logs/sqlErrors.txt"; 
    System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Append); 
    System.IO.StreamWriter sw = new System.IO.StreamWriter(fs); 

    sw.WriteLine("=======BEGIN ERROR LOG======="); 
    sw.WriteLine(DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString()); 
    sw.WriteLine("Query = " + query); 
    sw.WriteLine("User = " + HttpContext.Current.Session["UserID"]); 
    sw.WriteLine("Error Message = " + ex.Message); 
    sw.WriteLine("Message Source:"); 
    sw.WriteLine(ex.Source); 
    sw.WriteLine("============================="); 
    sw.WriteLine("Message Target:"); 
    sw.WriteLine(ex.TargetSite); 
    sw.WriteLine("============================="); 
    sw.WriteLine("Stack Trace:"); 
    sw.WriteLine(ex.StackTrace); 
    sw.WriteLine("========END ERROR LOG========"); 
    sw.WriteLine(""); 

    sw.Close(); 
    fs.Close(); 
} 

有沒有辦法通過整個字符串,參數包括,用於記錄作爲我在這裏?我想到的唯一方法應該是將查詢傳遞給日誌記錄功能,並構建一個for循環來將每個參數記錄爲一個單獨的項目。由於其中一些查詢有許多參數,並且我不會用一個簡單的字符串獲得完整的查詢,所以這不是最理想的解決方案。

回答

3

什麼:

// ... 
catch (IBM.Data.Informix.IfxException ex) 
{ 
    LogError(ex, query); // NOTE 
    SendErrorEmail(ex, query.CommandText); 
    DisplayError(); 
} 

,創建這樣一個過載:

private void LogError(IfxException ex, IfxCommand query) 
{ 
    StringBuilder sb = new StringBuilder(); 
    sb.Append(String.Format("{0}\n", query.CommandText)); 
    foreach (IDataParameter parameter in query.Parameters) 
     sb.Append(String.Format("\t{0} = {1}\n", 
      parameter.ParameterName, parameter.Value)); 

    LogError(ex, sb.ToString()); 
} 
+0

雖然我工作,但我改變了一下。我將這些更改添加爲答案,以便您可以看到我所做的。謝謝! – Ben

+0

不錯,我沒有測試過這個代碼=) –

+0

我遇到了一個場景,我必須記錄所有的查詢,並使用了它的值,並找到了答案。好一個!!正是我想要的:http://i.imgur.com/Xqgl3et.png感謝魯本斯:) – Latheesan

0

魯本:因爲我既想通過查詢到LOGERROR和SendErrorEmail功能

,我爲這種方法提供了獨特的功能。我還調整了您的版本,以自動替換參數點(例如,查詢中的「cmt_slmno =?」),而不是製作參數列表。這裏的結果:

private string RecreateQuery(IfxCommand query) 
{ 
    StringBuilder sb = new StringBuilder(); 
    sb.Append(query.CommandText); 
    foreach (IfxParameter parameter in query.Parameters) 
    sb.Replace(" ? ", string.Format(" {0} ", parameter.Value.ToString())); 
    return sb.ToString(); 
} 

而相應調整catch語句:

catch (IBM.Data.Informix.IfxException ex) 
{ 
    string errorQuery = RecreateQuery(query); 
    LogError(ex, errorQuery); 
    SendErrorEmail(ex, errorQuery); 
    DisplayError(); 
} 

這種方法有一個無賴的潛在問題?在文本中被替換,例如,如果語句在試圖設置的字符串中有問號。這應該是非常罕見的,我在這個應用程序中使用的數據,並用上面的空格圍繞問號應該涵蓋除了用戶放入的非常罕見的,奇怪格式的字符串。