2

我使用 SQL Server 2008 和 ASP.NET C#,并且我有一个返回一些计算行的存储过程。

我想在执行该过程之前检查参数值,如果参数值错误,我想返回自定义错误消息。

在 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 有错误。

我有一些想法,但我只想知道你的观点和最好的方法。

谢谢。

4

2 回答 2

1

根据此http://msdn.microsoft.com/en-us/library/ms178592.aspx,当您自己提供消息字符串时,您将获得 50000 的消息 ID。我想你可以在你的 C# 代码中测试它。

或者,您可以改为在 SP 中指定 MsgID(值 > 50000),并根据客户端代码中的 MsgID 提供错误消息。

于 2011-07-15T11:27:34.737 回答
0

只需将逻辑一分为二。我的意思是在一个存储过程中具有“参数检查”逻辑,其余的在另一个 SP 中。在“检查”SP 中,使用输出参数来获取您想要返回的任何代码或错误文本。

第二个 SP 也可以先调用 SP 以确保它不会收到错误数据。

然后 C# 应该首先调用“检查”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
于 2011-07-15T11:15:38.783 回答