Как обрабатывать ошибки в результатах хранимых процедур ColdFusion? - PullRequest
0 голосов
/ 24 августа 2018

Я использую ColdFusion для вызова хранимой процедуры для вставки или обновления данных пользователя.Эти две транзакции разделены на две процедуры.Мой код SQL должен возвращать количество строк 1 или 0, зависит от того, была ли транзакция успешной или нет.Если транзакция не удалась, мне интересно, как лучше в этом случае обрабатывать ошибки?Обе cfstoredproc переносятся в блок try / catch, но в случае, если в процедуре SQL произошла ошибка, моя переменная Count в наборе результатов вернет 0, а try / catch не зарегистрирует ошибку, возвращенную процедурой.Вот мой пример кода:

<cftry>
    <cfif trim(arguments.process) EQ "Insert">
        <cfstoredproc procedure="InsertRec" datasource="#dsn#">
            <cfprocparam dbvarname="@Status" value="#trim(arguments.status)#" cfsqltype="cf_sql_bit" />
            <cfprocparam dbvarname="@Code" value="#trim(arguments.frmcode)#" cfsqltype="cf_sql_char" maxlength="2" null="#!len(trim(arguments.code))#" />
            <cfprocparam dbvarname="@Name" value="#trim(arguments.name)#" cfsqltype="cf_sql_varchar" maxlength="50" null="#!len(trim(arguments.name))#" />
            <cfprocresult name="Result"/>
        </cfstoredproc>
    <cfelse>
        <cfstoredproc procedure="UpdateRec" datasource="#dsn#">
            <cfprocparam dbvarname="@Status" value="#trim(arguments._status)#" cfsqltype="cf_sql_bit" />
            <cfprocparam dbvarname="@Code" value="#trim(arguments.code)#" cfsqltype="cf_sql_char" maxlength="2" null="#!len(trim(arguments.code))#" />
            <cfprocparam dbvarname="@Name" value="#trim(arguments.name)#" cfsqltype="cf_sql_varchar" maxlength="50" null="#!len(trim(arguments.name))#" />
            <cfprocresult name="Result"/>
        </cfstoredproc>
    </cfif>

    <cfset local.fnResults = {
         status : "200", 
         message : "Record successully saved!", 
         recCount : Result.Count
    }>

    <cfcatch type="any">
         <cfset local.fnResults = {
             error : cfcatch, <!--- I use this just for testing purpose. --->
             status : "400",
             message : "Error! Please contact your administrator."
         }>
    </cfcatch>
</cftry>

Код выше возвращает столбец / переменную Count, как я уже упоминал из Result set.Если процесс успешно выполнен, пользователь получит уведомление с сообщением.Если что-то не так, я хотел бы отправить им сообщение, которое находится в моем блоке catch.Вот код SQL:

CREATE PROCEDURE [dbo].[InsertRec] 
    @Status BIT = NULL,
    @Name VARCHAR(50) = NULL,
    @Code CHAR(2) = NULL
AS
    SET NOCOUNT ON
    SET XACT_ABORT ON
    BEGIN TRY
        BEGIN
            INSERT INTO dbo.Books(
                Status,Name,Code
            )
            VALUES(
                @Status,@Name,@Code
            )
            SELECT @@ROWCOUNT AS Count;
        END
    END TRY
    BEGIN CATCH
        SELECT 
            @@ROWCOUNT AS Count, 
            ERROR_PROCEDURE() AS ErrorProcedure,
            ERROR_LINE() AS ErrorLine,
            ERROR_NUMBER() AS ErrorNumber,
            ERROR_MESSAGE() AS ErrorMessage,
            CURRENT_TIMESTAMP AS DateTime
    END CATCH

Я только показал код вставки SQL, поскольку процедура обновления такая же.Когда я использую, я вижу это сообщение, если что-то пошло не так.Это как раз тот пример, когда я попытался вставить первичный ключ, который уже существует специально:

COUNT   
0
DATETIME        
2018-08-24 07:00:01.58
ERRORLINE   
16
ERRORMESSAGE    
Violation of PRIMARY KEY constraint 'PK_Books'. Cannot insert duplicate key in object 'dbo.Books'. The duplicate key value is (44).
ERRORNUMBER 
2627    
ERRORPROCEDURE
InsertRec

ColdFusion не перехватывает эту ошибку.Есть ли способ отловить эту ошибку, когда я использую ColdFusion для вызова хранимой процедуры в наборе результатов?

1 Ответ

0 голосов
/ 29 августа 2018

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

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

DECLARE @SUCCESS BIT = 1;
DECLARE @MSG VARCHAR(50) = 'Some default success message.'

Обновите эти значения в вашем CATCH утверждении:

BEGIN CATCH
    SET @SUCCESS = 0;
    SET @MSG = 'There was a problem ...';
    SELECT 
        @SUCCESS as success,
        @MSG as message,
        @@ROWCOUNT AS Count, 
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage,
        CURRENT_TIMESTAMP AS DateTime
END CATCH

Но также верните эти значения после CATCHтак что proc всегда возвращает статус.

SELECT 
    @SUCCESS as success,
    @MSG as message

Это даст вам удобное сообщение, а также фактическую ошибку SQL (когда это произойдет), которая может быть записана по мере необходимости.

...