2011-07-15 58 views
2

我使用SQL Server 2008和ASP.NET C#,並且我有一個存儲過程返回一些計算行。SQL Server和如何處理沒有衝突的錯誤類型

我想在執行該過程之前檢查參數值,並且如果參數值錯誤,我想返回自定義錯誤消息。

在UI方面,我必須根據錯誤類型返回不同的文本並使用不同的窗口。例如:

  • 參數值錯誤時出錯。
  • 未處理錯誤。

我目前在數據庫中使用這種SP,但我嘗試使用狀態參數甚至嚴重性參數來標識錯誤的類型。但是,與未處理的錯誤相比,我返回了與參數錯誤相同的狀態編號,所以出現了錯誤的窗口。如果我使用嚴重級別,我想SP在某些情況下可能會返回具有相同嚴重性級別的錯誤。

我給你一個簡單的例子,有一個更好的視野:

CREATE PROCEDURE dbo.GetData 
    @Date1 date, 
    @Date2 date 
AS 
BEGIN 

    -- check the parameters 
    IF @Date2 < @Date1 
    BEGIN 
     RAISERROR(N'Date 2 cannot be less than Date 1', 16, 2); -- <= Here State 2 
     return 
    END 

    -- process here... 
    DECLARE @Table1 TABLE (name nvarchar(50) NOT NULL) 

    -- Supposing you have to insert a row with a NULL value 
    INSERT INTO @Table1 VALUES (NULL); 
    -- Thus, this query returns this error with the state 2 as well! 
    --Msg 515, Level 16, State 2, Procedure GetData, Line 21 
    --Cannot insert the value NULL into column 'name', table '@Table1'; column does not allow nulls. INSERT fails. 

    SELECT 'Record 1'; 
    SELECT 'Record 2'; 
END 

從C#:以上

List<string> data = new List<string>(); 

protected void Button1_Click(object sender, EventArgs e) 
{ 
    string errorMessage = string.Empty; 
    bool isErrorFromChecking = false; 

    if (GetValues(ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString, 
       new DateTime(2011, 01, 01), new DateTime(2011, 02, 01), 
       ref isErrorFromChecking, ref errorMessage)) 
    { 
     Label1.Text = data[0].ToString(); 
     return; 
    } 

    if (isErrorFromChecking) 
    { 
     Label1.Text = errorMessage; 
     return; 
    } 
    Label1.Text = string.Format("Internal Error: {0}.", errorMessage); 
} 

private bool GetValues(string connectionString, DateTime date1, DateTime date2, 
      ref bool isErrorFromChecking, ref string errorMessage) 
{ 
    data = new List<string>(); 
    try 
    { 
     using (SqlConnection sqlCon = new SqlConnection(connectionString)) 
     { 
      sqlCon.Open(); 
      SqlCommand sqlCmd = new SqlCommand(); 
      sqlCmd.Connection = sqlCon; 
      sqlCmd.CommandType = CommandType.StoredProcedure; 
      sqlCmd.CommandText = "dbo.GetData"; 

      sqlCmd.Parameters.AddWithValue("Date1", date1); 
      sqlCmd.Parameters.AddWithValue("Date2", date2); 

      SqlDataReader reader = sqlCmd.ExecuteReader(); 
      while (reader.Read()) 
      { 
       data.Add(reader[0].ToString()); 
      } 
      reader.Close(); 
      sqlCon.Close(); 
     } 
    } 
    catch (SqlException ex) 
    { 
     if (ex.State == 2) 
     { 
      isErrorFromChecking = true; 
      errorMessage = ex.Message; 
      return false; 
     } 
     isErrorFromChecking = false; 
     errorMessage = ex.Message; 
     return false; 
    } 
    catch (Exception ex) 
    { 
     isErrorFromChecking = false; 
     errorMessage = ex.Message; 
     return false; 
    } 

    return true; 
} 

在代碼中,日期是正確的,但程序不會返回消息「內部錯誤:...」雖然SP有錯誤。

我有一些想法,但我只是想知道你的觀點和最好的方式來做到這一點。

謝謝。

回答

0

簡單地將邏輯分成兩部分。我的意思是在一個存儲過程中有'參數檢查'邏輯,剩下的在另一個存儲過程中。 在'檢查'SP中使用輸出參數來獲取您想返回的任何代碼或錯誤文本。

第二個SP也可以先調用SP來確保它沒有發送錯誤的數據。

然後C#應該先調用'check'SP並查看返回的內容。

另一種方法是對錯誤條件使用輸出參數並返回空數據集。

CREATE PROCEDURE spTest (@param1 int, @ErrorText varchar(50) OUTPUT) 
AS 
BEGIN 
    SET @ErrorText = NULL 
    IF @Param1 = 1 
    BEGIN 
     SET @ErrorText = 'I really cant except 1 as a parameter' 
     SELECT NULL as QueryPlaceholderCol 
    END 
    ELSE 
    BEGIN 
     SELECT 3.141 AS QueryPlaceholderCol 
    END 
END 

要在T-SQL測試:

DECLARE @ReturnedError VARCHAR(50) 
EXEC spTest 1,@ReturnedError OUTPUT 
SELECT CASE WHEN @ReturnedError IS NULL THEN 'Worked Fine' ELSE @ReturnedError END AS Outputs 
EXEC spTest 1423,@ReturnedError OUTPUT 
SELECT CASE WHEN @ReturnedError IS NULL THEN 'Worked Fine' ELSE @ReturnedError END AS Outputs 
+0

所以在你的建議中,'檢查'SP被稱爲2次。但這是個好主意!有沒有辦法做到這一點,保持「檢查」邏輯在同一個SP比過程?我的意思是,有時候比起在sp開頭的兩個日期來比較它並不容易,它可能在sp的結尾。 – Dan

+0

是的,在我的例子中它被稱爲兩次。當然,如果SP沒有在其他地方使用,您可以完全刪除SP中的支票,並依靠客戶端應用程序始終首先調用支票。 我已經擴大了答案,給出了另一種方法 –

+0

謝謝@Joel您的答案。實際上,我最終實現了OUTPUT參數,就像您的替代建議。這對我來說是最好的解決方案,因爲在這個階段我不使用用戶定義的消息,並且我想避免在這個項目中使用它們。 – Dan

1

根據這一http://msdn.microsoft.com/en-us/library/ms178592.aspx你會得到50000的消息ID,當你提​​供你自己的消息字符串。我想你可以在你的C#代碼中進行測試。

或者您可以在SP中指定一個MsgID(值> 50000),並根據客戶端代碼中的MsgID提供錯誤消息。