SQL Server и как обработать тип ошибки без конфликта - PullRequest
2 голосов
/ 15 июля 2011

Я использую SQL Server 2008 и ASP.NET C #, и у меня есть хранимая процедура, которая возвращает некоторые вычисленные строки.

Я хочу проверить значения параметров перед выполнением процесса и вернуть пользовательское сообщение об ошибке, если значения параметров неверны.

На стороне пользовательского интерфейса я должен вернуть другой текст и использовать другое окно в соответствии с типом ошибки. Пример:

  • Ошибки при неправильных значениях параметров.
  • Не обработанные ошибки.

В настоящее время я использую этот тип 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 имеет ошибку.

У меня есть некоторые идеи, но я просто хочу знать вашу точку зрения и лучший способ сделать это.

Спасибо.

Ответы [ 2 ]

1 голос
/ 15 июля 2011

В соответствии с этим http://msdn.microsoft.com/en-us/library/ms178592.aspx вы получите идентификатор сообщения 50000, когда сами предоставите строку сообщения.Я думаю, вы могли бы проверить это в своем коде C #.

Или вы могли бы вместо этого указать MsgID (значение> 50000) в SP и предоставить сообщение об ошибке на основе MsgID в коде клиента.

0 голосов
/ 15 июля 2011

Просто разделите логику на две части.Под этим я подразумеваю логику «проверки параметров» в одной хранимой процедуре, а остальные - в другом SP.В 'check' SP используйте выходные параметры для получения любых кодов или текста ошибки, который вы хотите вернуть.

Второй SP также может сначала вызвать SP, чтобы убедиться, что он не получает неверные данные.

Затем C # должен сначала вызвать SP 'check' и посмотреть, что возвращается.

Альтернативой является использование выходного параметра для условия ошибки и возврат пустого набора данных.

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
...