2011-07-15 11 views
2

SQL Server 2008とASP.NET C#を使用しており、計算された行を返すストアドプロシージャがあります。SQL Serverと矛盾のないエラーの種類を処理する方法

プロセスを実行する前にパラメータの値を確認したいのですが、パラメータ値が間違っている場合はカスタムエラーメッセージを返したいと思います。

UI側では、別のテキストを返し、エラータイプに応じて別のウィンドウを使用する必要があります。例:

  • パラメータ値が間違っているときのエラー。
  • 処理されないエラーが発生しました。

私は現在、データベースでこの種のSPを使用していますが、エラーの種類を識別するためにstate引数とseverity引数を使用しようとしました。しかし私は、私のパラメータエラーと同じ状態番号を返す非対処エラーといくつかの競合があり、間違ったウィンドウが表示されます。重大度を使用すると、同じ重大度のエラーが返されることがあります。 #Cからの

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 

私はあなたをより見やすく持っている簡単な例を与える上記のコードで

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

ロジックを2つに分割します。これにより、私は、1つのストアドプロシージャに 'パラメータチェック'ロジックがあり、残りのSPには残りのロジックがあることを意味します。 'check'では、SPは出力パラメータを使用して、返すコードやエラーテキストを取得します。

第2のSPは、悪意のあるデータが送信されていないことを確認するために、最初にSPを呼び出すこともできます。

C#は、まず「チェック」SPを呼び出し、返される内容を確認する必要があります。

エラー条件に出力パラメータを使用し、空のデータセットを返すこともできます。 T-SQLでテストするには

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 

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の始めに2つの日付を比較するのは簡単ではないことを意味し、spの終わりにある可能性があります。 – Dan

+0

はい、私の例では2回呼び出されます。もちろん、SPが他の場所で使用されていない場合は、SPからチェックを完全に削除し、常にチェックを最初に呼び出すクライアントアプリケーションに依存することができます。 私は別のアプローチを与えるために答えを広げました –

+0

あなたの答えは@Joelありがとうございます。実際には、私はついにあなたの代替案のようにOUTPUTパラメータを実装しました。この段階ではユーザー定義のメッセージを使用しないため、これは私にとって最適なソリューションです。このプロジェクトでは使用しないでください。 – Dan

1

このhttp://msdn.microsoft.com/en-us/library/ms178592.aspxによると、あなたがメッセージ文字列を自分で提供する場合、あなたが50000のメッセージIDを取得します。私はあなたのC#コードでそれをテストできると思います。

代わりに、SPにMsgID(値> 50000)を指定して、クライアントコードのMsgIDに基づいてエラーメッセージを提供することができます。

関連する問題