Как захватить все от вкладки сообщений с SQL Server до приложения C #? - PullRequest
0 голосов
/ 25 марта 2019

Немного предыстории моего приложения.

Я работаю над File Watcher службой Windows, используя C # , который ищет .bak файлов в определенной папке, а затем используйте ее для восстановления базы данных, к которой принадлежит этот файл.

В восстановленной базе данных есть хранимая процедура, которая вызывает 10 различных хранимых процедур.Это File Watcher's функциональность для выполнения хранимой процедуры после восстановления.

Хранимая процедура - [1_IMPORT_DATA_AND_PROCESS_ALL], которая вызывает внутри себя 10 различных хранимых процедур.

Это метод, который выполняет хранимую процедуру после завершения восстановления.

// Trigger Stored Procedure after restore. 
private void triggerSP(String connectionStr)
{
    // This doesn't open the Connection. conn.Open() has to be explicitly called.

    SqlConnection conn = new SqlConnection(connectionStr);
    try
    {

    conn.Open();
    conn.FireInfoMessageEventOnUserErrors = true;
    // Capture messages returned by SQL Server.
    conn.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
    {

        message += " -> " + e.Message + " -> ";
    };
    //conn.InfoMessage += new SqlInfoMessageEventHandler(cn_InfoMessage);

    //.create a command object identifying the stored procedure.
    SqlCommand cmd = new SqlCommand("[dbo].[1_IMPORT_DATA_AND_PROCESS_ALL]", conn);
    cmd.CommandTimeout = 0;
    // 2. set the command object so it knows to execute a stored procedure.
    cmd.CommandType = CommandType.StoredProcedure;

    // Add a check here as well.
    // execute the command.
    SqlDataReader rdr = cmd.ExecuteReader();


    string[] info = new string[] { "Message: \n" + message };
    WriteToFile(info);

    // Since we are not using - using block we have to explicitly call Close() to close the connection.
    conn.Close();
    }
    catch (SqlException SqlEx){
    string[] error = new string[3] ;

    string msg1 = "Errors Count:" + SqlEx.Errors.Count;
    string msg2 = null;

    foreach (SqlError myError in SqlEx.Errors)
        msg2 += myError.Number + " - " + myError.Message + "/" ;

    conn.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
    {
        message += "\n" + e.Message;
    };

    error[0] = msg1;
    error[1] = msg2;
    error[2] = message;

    WriteToFile(error);
    }

    finally
    {
    //call this if exception occurs or not
    //in this example, dispose the WebClient
    conn.Close();
    }

}

Проблема

Я получаю обратно сообщения только из самой первой хранимой процедуры, т.е. [1_IMPORT_DATA_AND_PROCESS_ALL], а не из хранимой процедуры, которая вызывается из [1_IMPORT_DATA_AND_PROCESS_ALL], как показано ниже.

enter image description here

Как только 1-й Sp вызывает другого SP, мои коды перестают читать Сообщения.

Я хочу захватить все Сообщениякоторые печатаются, что-то вроде этого (изображение ниже), которые являются фактическими сообщениями, которые печатаются, когда я выполняю SP в SSMS.

enter image description here

Эта конкретная строка извлекает Сообщения от SP

conn.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
    {
        message += " -> " + e.Message + " -> ";
    };

До сих пор я ссылался на все, что касается этого вопроса, и это производных .

Я не могу изменитьХранимая процедура теперь я могу вносить изменения только в свое приложение C #.

Надеюсь, мой вопрос понятен.

1 Ответ

0 голосов
/ 26 марта 2019

Добрый день,

Примечание! Это сообщение не помечено как "вики сообщества" и поэтому оно написано конкретным человеком под его именем, и оно не является общей статьей. Если у вас есть комментарии, используйте комментарии вместо того, чтобы менять контент, который ОП должен был предоставить (например, дополнительные пункты обучения в контенте). Спасибо!

В следующем скрипте я представляю пример обработки вложенной ошибки хранимой процедуры. Основная идея заключается в том, чтобы использовать TRY / CATCH, чтобы предотвратить возникновение ошибки и остановить транзакцию, а OUTPUT используется для возврата информации об ошибке в верхний уровень SP

Это только базовый пример ...

CREATE or ALTER PROCEDURE L1 (
    @InputInt int,
    @ErrMessage NVARCHAR(MAX) OUTPUT,
    @ErrNum INT OUTPUT
)AS
    SELECT @@NESTLEVEL AS 'Inner Level'; -- this information present the level of the SP during the execution. It is not needed for the solution but for the sake of the learning and understanding of nested SP
    Select 'Start L1'

    BEGIN TRY  
        -- When the ionput is 0 we Generate a divide-by-zero error.  
        SELECT 1/@InputInt;  
    END TRY  
    BEGIN CATCH
        SET @ErrMessage = ERROR_MESSAGE()
        SELECT @ErrMessage
    END CATCH;

    SET @ErrNum = @@ERROR
    IF (@ErrNum > 0) Begin
       SELECT 'L1 error Number: ' + CONVERT(NVARCHAR(10), @ErrNum)
       Return
    END
    ELSE
       select 'L1 OK'
GO

CREATE or ALTER PROCEDURE L2 (
    @InputInt int
) AS   
    Declare @ErrMessage NVARCHAR(MAX) = '', @ErrNum INT = 0
    SELECT @@NESTLEVEL AS 'Outer Level';
    BEGIN TRY
        EXEC L1 @InputInt, @ErrMessage, @ErrNum;
    END TRY
    BEGIN CATCH
        SELECT 'There was error!'
        select @@ERROR
    END CATCH
GO

EXECUTE L2 1 -- OK
GO

EXECUTE L2 0; --Raise error in the nested stored procedures 
GO
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...