【问题标题】:Try...catch not working when surrounding stored procedure executionTry...catch 在执行存储过程时不起作用
【发布时间】:2021-04-09 00:26:05
【问题描述】:

在我的 web api 数据访问层中,Asp.net TRY CATCH 没有捕捉到存储过程的失败。注意:此代码模板用于丢弃我的 web api 数据访问层并且工作正常。只是在这种情况下不是。诡异的!! (我在底部包含了一个类似且有效的示例)。

我预计存储过程会失败,因为没有符合条件的行。所以在这种情况下,我会引发一个错误 (RAISERROR),它会在我的错误日志表中写入一个条目。

当我通过 SSMS 执行它或运行调用执行存储过程的 web api 的 web 应用程序时会发生这种情况。

包含 2 个条目的错误日志表。 1 通过 SSMS 运行存储过程,另一个通过运行我的网络应用程序。

问题是web api数据访问层代码执行没有捕捉到存储过程返回的错误。它不会进入 CATCH。

这是从我的 web api 控制器调用的 web api 数据访问层函数。它的 TRY CATCH 不能正常工作:

public List<BlogPublishedCategory> 
GetBlogCategorysInBlogsPublishedList(string userName, string ipAddress)
{
   string userFriendlyMessage = "Unable to get the blog categorys in the 
   blogs published list. We have been notified and are working to resolve 
   this. Please do not continue.";

    List<BlogPublishedCategory> blogPublishedCategoryList = new 
    List<BlogPublishedCategory>();

    SqlDataReader blogCategorysInBlogsDataReader = null;

    try
    {
        dbFunc.OpenDB();

        SqlCommand cmd = new SqlCommand("dbo.GetBlogCategorysInBlogsPublished", dbFunc.objConn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Clear();

        cmd.Parameters.AddWithValue("@a_UserName", userName);
        cmd.Parameters.AddWithValue("@a_IpAddress", ipAddress);

        blogCategorysInBlogsDataReader = cmd.ExecuteReader();

        while (blogCategorysInBlogsDataReader.Read())
        {
            // Add to the list of BlogPublishedCategory - creates a new row for the collection.
            blogPublishedCategoryList.Add(new BlogPublishedCategory
            {
                BlogCategoryId = Convert.ToInt32(blogCategorysInBlogsDataReader["BlogCategoryId"]),
                BlogCategoryDescr = blogCategorysInBlogsDataReader["BlogCategoryDescr"].ToString(),
            });
        }

        // Return the blogPublishedCategoryList object.
        return blogPublishedCategoryList;
    }
    catch (SqlException sqlex)
    {
    if (sqlex.Message.Contains("Critical"))
        {
            currentDateTime = DateTime.Now;
            sendAlertEmailResult = SendAlertEmailToStaff(currentDateTime, userName, ipAddress);

            if (sendAlertEmailResult == "")
            {
                throw new Exception(userFriendlyMessage);
            }
            else
            {
                throw new Exception("In DataAccessLayer/GetBlogCategorysInBlogsPublishedList(). Sending an alert email for the initial sql exception error: " + sqlex.Message + ". Now getting this error: " + sendAlertEmailResult);
            }
        }
        else
        {
            errorMessage = "Sql Exception Error in DataAccessLayer/GetBlogCategorysInBlogsPublishedList(). Using 'GetBlogCategorysInBlogsPublished' s/p. Error: " + sqlex.Message;

            currentDateTime = DateTime.Now;
            processErrorLogAndSendAlertEmailResult = ProcessErrorLogAndSendAlertEmail(currentDateTime, userName, errorMessage, additionalInfoForLog, ipAddress);

            if (processErrorLogAndSendAlertEmailResult != "")
            {
                throw new Exception("Error in DataAccessLayer/GetBlogCategorysInBlogsPublishedList(). Using 'GetBlogCategorysInBlogsPublished' s/p. Logging the initial sql exception error: " + sqlex.Message + ". Now getting this error: " + processErrorLogAndSendAlertEmailResult);
            }
            else
            {
                throw new Exception(userFriendlyMessage);
            }
        }
    }
    catch (Exception ex)
    {
        errorMessage = "Error in DataAccessLayer/GetBlogCategorysInBlogsPublishedList(). Using 'GetBlogCategorysInBlogsPublished' s/p. Error: " + ex.Message;

        currentDateTime = DateTime.Now;
        processErrorLogAndSendAlertEmailResult = ProcessErrorLogAndSendAlertEmail(currentDateTime, userName, errorMessage, additionalInfoForLog, ipAddress);

        if (processErrorLogAndSendAlertEmailResult != "")
        {
            throw new Exception("Error in DataAccessLayer/GetBlogCategorysInBlogsPublishedList(). Using 'GetBlogCategorysInBlogsPublished' s/p. Logging the initial error: " + ex.Message + ". Now getting this error: " + processErrorLogAndSendAlertEmailResult);
        }
        else
        {
            throw new Exception(userFriendlyMessage);
        }
    }
    finally
    {
        if (blogCategorysInBlogsDataReader != null)
        {
            blogCategorysInBlogsDataReader.Close();
        }

        dbFunc.CloseDB();
    }
}

GetBlogCategorysInBlogsPublished 存储过程(失败,因为行数为 0):

USE [DBGbngDev]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo]. 
[GetBlogCategorysInBlogsPublished]') AND type in (N'P', N'PC'))
    BEGIN
       DROP PROCEDURE [dbo].GetBlogCategorysInBlogsPublished
    END
GO

CREATE procedure [dbo].[GetBlogCategorysInBlogsPublished] 

@a_UserName              varchar(250) = NULL,
@a_IpAddress             varchar(250) = NULL

AS 
BEGIN

DECLARE @RowCount                  int,
        @ReturnCode                int,
        @CurrentDateTime           datetime,  
        @Message                   varchar(max) = '',
        @ApiMessageOut             varchar(max),
        @ApiAccessSwitchOut        bit

DECLARE @ErrorLine          AS INT;
DECLARE @ErrorMessage       AS VARCHAR(2048);
DECLARE @ErrorNumber        AS INT; 
DECLARE @ErrorSeverity      AS INT; 
DECLARE @ErrorState         AS INT; 
DECLARE @DatabaseName       AS VARCHAR(255);
DECLARE @ServerName         AS VARCHAR(255);
DECLARE @ErrorDescription   AS VARCHAR(MAX);
DECLARE @CRLF               AS VARCHAR(2);

SELECT @CurrentDateTime = GETDATE()
    
BEGIN TRY

   SET NOCOUNT ON;

   IF ( ( @a_UserName  = '' OR @a_UserName  IS NULL ) 
   OR ( @a_IpAddress = '' OR @a_IpAddress IS NULL ) )
      BEGIN
         SELECT @Message = 'Critical Error - procedure GetBlogCategorysInBlogsPublished - invalid 
         parameters. They cannot be null or empty.' 

         IF ( @a_UserName = '' OR @a_UserName IS NULL )
             BEGIN
                SET @a_UserName = 'No "user name" parameter provided.'
             END

         IF ( @a_IpAddress = '' OR @a_IpAddress IS NULL )
             BEGIN
                SET @a_IpAddress = 'No "ip address" parameter provided.'
             END

        RAISERROR (@Message, 16, 1)
      END
   ELSE
      BEGIN
           -- Do the API security check. If this user is valid, you can continue with further
           processing.
           SELECT @ReturnCode = -1
           EXECUTE @ReturnCode = dbo.GetApiAccess
                              @CurrentDateTime,
                              @a_UserName,
                              @a_IpAddress,
                              @a_ApiAccessSwitchFromGet = @ApiAccessSwitchOut OUTPUT,
                              @a_ApiMessageFromGet = @ApiMessageOut OUTPUT

           IF @ReturnCode = -1
                BEGIN 
                   RAISERROR ('Critical Error - procedure GetBlogCategorysInBlogsPublished failed during execute of procedure GetApiAccess.', 16, 1 )
                END
    
           -- Web api access was granted. 
           IF @ApiAccessSwitchOut = 1
               BEGIN    
                   SELECT DISTINCT (a.BlogCategoryId) as BlogCategoryId
                                   ,a.BlogCategoryDescr as BlogCategoryDescr
                   FROM dbo.BlogCategory a
                   JOIN dbo.Blog b On ( a.BlogCategoryId = b.BlogCategoryId )
                   WHERE ( b.PublishSwitch = 1 AND b.CanBeSeenSwitch = 1 )
                   ORDER BY a.BlogCategoryId asc  

                   SELECT @ReturnCode = @@ERROR,
                          @RowCount = @@ROWCOUNT

                   IF @ReturnCode <> 0
                       BEGIN 
                           SELECT @Message = 'Critical Error - procedure GetBlogCategorysInBlogsPublished failed during the select.'
                           RAISERROR (@Message, 16, 1)
                       END
         
                   IF @RowCount = 0
                       BEGIN
                           SELECT @Message =  'Critical Error - procedure GetBlogCategorysInBlogsPublished failed during the select. There are no BlogCategory entries.' 
                           RAISERROR (@Message, 16, 1)
                       END  
               END
           ELSE
               BEGIN
                    -- Web api access was NOT granted. The user did not have permission to use the web api or there is an error in the GetApiAccess procedure.
                    RAISERROR (@ApiMessageOut, 16, 1 )
              END
      END
    
   -- Returns success.
   RETURN 0

END TRY

BEGIN CATCH
    SELECT 
          @ErrorLine = ERROR_LINE()
          -- ERROR_MESSAGE() contains the RAISERROR message raised above.
        , @ErrorMessage = ERROR_MESSAGE()
        , @ErrorNumber = ERROR_NUMBER()
        , @ErrorSeverity = ERROR_SEVERITY()
        , @ErrorState = ERROR_STATE()
        , @DatabaseName = CAST(DB_NAME() AS VARCHAR)
        , @ServerName = CAST(SERVERPROPERTY ( 'ServerName' ) AS VARCHAR)
        , @CRLF  = CHAR(13) + CHAR(10)

        SET @ErrorDescription = 'From stored procedure: '  + ERROR_PROCEDURE() 
                                + '. Error Line: '  + CAST(@ErrorLine AS VARCHAR)
                                + '. Error Message: ' + @ErrorMessage
                                + ' Error Number: ' + CAST(@ErrorNumber AS VARCHAR)
                                + '. Error Severity: ' + CAST(@ErrorSeverity AS VARCHAR)
                                + '. Error State: ' + CAST(@ErrorState AS VARCHAR)
                                + '. Database Name: '  + @DatabaseName
                                + '. Server Name: ' + @ServerName

    IF (XACT_STATE() <> 0)
        BEGIN
           ROLLBACK TRANSACTION 
        END
 
    IF (@ErrorSeverity = 16) AND (@ErrorState = 2)
        BEGIN 
           RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState)
        END      
    ELSE
        BEGIN 
           -- Log the critical error.   
           BEGIN TRY
              EXEC dbo.InsertBlogErrorLog
                         @a_LogDateTime = @CurrentDateTime,    
                         @a_UserName = @a_UserName,     
                         @a_UserIpAddress = @a_IpAddress,        
                         @a_ObjectID = @@PROCID,
                         @a_MessageType = 'S/P Critical Error',
                         @a_LogMessage = @ErrorDescription           
           END TRY

           BEGIN CATCH
              -- Stack the messages.
              SELECT @Message = 'Critical Error - procedure InsertBlogErrorLog failed. A log entry cannot be made. Do not continue. Contact IT. Initial error message: ' + @ErrorMessage
              RAISERROR(@Message, 16, 1) 
           END CATCH

           SELECT @message = 'Critical Error - do not continue. Contact IT and provide this log date: ' + Convert(VARCHAR, @CurrentDateTime,21)
           RAISERROR(@Message, 16, 1)                 
        END

     -- Returns failure.
     RETURN 1      

END CATCH
END

这是一个类似的示例,我在存储过程中强制出错以显示类似(几乎相同)的 Web api 数据访问层函数确实捕获了存储过程错误。

带有条目的错误日志表。从运行我的网络 api 开始。

确实捕获存储过程返回的错误的 Web api 数据访问层代码执行。它确实进入 CATCH 并执行我期望的处理。

这是从我的 web api 控制器调用的 web api 数据访问层函数。它的 TRY CATCH 工作正常:

public List<BlogCategory> GetBlogCategoryList(string userName, string ipAddress)
    {
        string userFriendlyMessage = "Unable to get blog categories. We have been notified and are working to resolve this. Please do not continue.";

        List<BlogCategory> blogCategoryList = new List<BlogCategory>();

        SqlDataReader blogCategoryDataReader = null;

        try
        {
            dbFunc.OpenDB();

            SqlCommand cmd = new SqlCommand("dbo.GetBlogCategory", dbFunc.objConn);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Clear();

            cmd.Parameters.AddWithValue("@a_UserName", userName);
            cmd.Parameters.AddWithValue("@a_IpAddress", ipAddress);

            blogCategoryDataReader = cmd.ExecuteReader();

              while (blogCategoryDataReader.Read())
            {
                blogCategoryList.Add(new BlogCategory
                {
                    BlogCategoryId = Convert.ToInt32(blogCategoryDataReader["BlogCategoryId"]),
                    BlogCategoryDescr = blogCategoryDataReader["BlogCategoryDescr"].ToString(),
                });
            }

            return blogCategoryList;
        }
        catch (SqlException sqlex)
        {
            if (sqlex.Message.Contains("Critical"))
            {
                // A "critical" error coming from the stored procedure.

                // So, send an alert email to a staff member (an Admin), but do NOT process the error log as it has been done already 
                // in the stored procedure.

                currentDateTime = DateTime.Now;
                sendAlertEmailResult = SendAlertEmailToStaff(currentDateTime, userName, ipAddress);

                if (sendAlertEmailResult == "")
                {
                    throw new Exception(userFriendlyMessage);
                }
                else
                {
                    throw new Exception("In DataAccessLayer/GetBlogCategoryList(). Sending an alert email for the initial sql exception error: " + sqlex.Message + ". Now getting this error: " + sendAlertEmailResult);
                }
            }
            else
            {
                // Not coming from the stored procedure. Like if the stored procedure above was not named properly, does not exist, parameter missing, etc.
                errorMessage = "Sql Exception Error in DataAccessLayer/GetBlogCategoryList(). Using 'GetBlogCategory' s/p. Error: " + sqlex.Message;

                // Log the error and send an alert email.
                currentDateTime = DateTime.Now;
                processErrorLogAndSendAlertEmailResult = ProcessErrorLogAndSendAlertEmail(currentDateTime, userName, errorMessage, additionalInfoForLog, ipAddress);

                if (processErrorLogAndSendAlertEmailResult != "")
                {
                    throw new Exception("Error in DataAccessLayer/GetBlogCategoryList(). Using 'GetBlogCategory' s/p. Logging the initial sql exception error: " + sqlex.Message + ". Now getting this error: " + processErrorLogAndSendAlertEmailResult);
                }
                else
                {
                    throw new Exception(userFriendlyMessage);
                }
            }
        }
        catch (Exception ex)
        {
            errorMessage = "Error in DataAccessLayer/GetBlogCategoryList(). Using 'GetBlogCategory' s/p. Error: " + ex.Message;

            currentDateTime = DateTime.Now;
            processErrorLogAndSendAlertEmailResult = ProcessErrorLogAndSendAlertEmail(currentDateTime, userName, errorMessage, additionalInfoForLog, ipAddress);

            if (processErrorLogAndSendAlertEmailResult != "")
            {
                throw new Exception("Error in DataAccessLayer/GetBlogCategoryList(). Using 'GetBlogCategory' s/p. Logging the initial error: " + ex.Message + ". Now getting this error: " + processErrorLogAndSendAlertEmailResult);
            }
            else
            {
                throw new Exception(userFriendlyMessage);
            }
        }
        finally
        {
            if (blogCategoryDataReader != null)
            {
                blogCategoryDataReader.Close();
            }

            dbFunc.CloseDB();
        }
    }

这是 GetBlogCategory 存储过程(它失败,因为我强制 rowcount = 0 ):

USE [DBGbngDev]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo]. 
[GetBlogCategory]') AND type in (N'P', N'PC'))
BEGIN
   DROP PROCEDURE [dbo].GetBlogCategory
END
GO

CREATE procedure [dbo].[GetBlogCategory]

@a_UserName         varchar(250) = NULL,
@a_IpAddress        varchar(250) = NULL 

AS 
BEGIN

  DECLARE @RowCount                  int,
          @ReturnCode                int,
          @CurrentDateTime           datetime,  
          @Message                   varchar(max) = '',
          @ApiMessageOut             varchar(max),
          @ApiAccessSwitchOut        bit

SELECT @CurrentDateTime = GETDATE()

DECLARE @ErrorLine      AS INT;
DECLARE @ErrorMessage       AS VARCHAR(2048);
DECLARE @ErrorNumber        AS INT; 
DECLARE @ErrorSeverity      AS INT; 
DECLARE @ErrorState     AS INT; 
DECLARE @DatabaseName       AS VARCHAR(255);
DECLARE @ServerName     AS VARCHAR(255);
DECLARE @ErrorDescription   AS VARCHAR(MAX);
DECLARE @CRLF           AS VARCHAR(2);
    
BEGIN TRY

   SET NOCOUNT ON;
   IF ( ( @a_UserName  = '' OR @a_UserName  IS NULL ) OR ( @a_IpAddress = '' OR @a_IpAddress IS NULL ) )
      BEGIN
         SELECT @Message = 'Critical Error - procedure GetBlogCategory - invalid parameters. They cannot be null or empty.' 

         IF ( @a_UserName = '' OR @a_UserName IS NULL )
             BEGIN
                SET @a_UserName = 'No "user name" parameter provided.'
             END

         IF ( @a_IpAddress = '' OR @a_IpAddress IS NULL )
             BEGIN
                SET @a_IpAddress = 'No "ip address" parameter provided.'
             END

        RAISERROR (@Message, 16, 1)
      END
   ELSE
      BEGIN
           -- Do the API security check. If this user is valid, you can continue with further processing.
           SELECT @ReturnCode = -1
           EXECUTE @ReturnCode = dbo.GetApiAccess
                              @CurrentDateTime,
                              @a_UserName,
                              @a_IpAddress,
                              @a_ApiAccessSwitchFromGet = @ApiAccessSwitchOut OUTPUT,
                              @a_ApiMessageFromGet = @ApiMessageOut OUTPUT

           IF @ReturnCode = -1
                BEGIN 
                   RAISERROR ('Critical Error - procedure GetBlogCategory failed during execute of procedure GetApiAccess.', 16, 1 )
                END
    
           -- Web api access was granted. 
           IF @ApiAccessSwitchOut = 1
               BEGIN
                   --SELECT BlogCategoryId as BlogCategoryId
                            --    ,BlogCategoryDescr as BlogCategoryDescr
                   --FROM dbo.BlogCategory
                   --ORDER BY BlogCategoryDescr asc  

                   --SELECT @ReturnCode = @@ERROR,
                --                @RowCount = @@ROWCOUNT

                   --IF @ReturnCode <> 0
                      -- BEGIN 
                         --  SELECT @Message = 'Critical Error - procedure GetBlogCategory failed during the select.'
                         --  RAISERROR (@Message, 16, 1)
                      -- END
             
                   SET @RowCount = 0

                   IF @RowCount = 0
                       BEGIN
                           SELECT @Message =  'Critical Error - procedure GetBlogCategory failed during the select. There are no entries.' 
                           RAISERROR (@Message, 16, 1)
                       END  
               END
           ELSE
               BEGIN
                    -- Web api access was NOT granted. The user did not have permission to use the web api or there is an error in the GetApiAccess procedure.
                    -- Pass the message returned from the GetApiAccess procedure.
                    RAISERROR (@ApiMessageOut, 16, 1 )
              END
      END
    
   -- Returns success.
   RETURN 0

END TRY

BEGIN CATCH

    SELECT 
            @ErrorLine = ERROR_LINE()
        -- ERROR_MESSAGE() contains the RAISERROR message raised above.
        , @ErrorMessage = ERROR_MESSAGE()
        , @ErrorNumber = ERROR_NUMBER()
        , @ErrorSeverity = ERROR_SEVERITY()
        , @ErrorState = ERROR_STATE()
        , @DatabaseName = CAST(DB_NAME() AS VARCHAR)
        , @ServerName = CAST(SERVERPROPERTY ( 'ServerName' ) AS VARCHAR)
        , @CRLF  = CHAR(13) + CHAR(10)


        SET @ErrorDescription = 'From stored procedure: '  + ERROR_PROCEDURE() 
                                + '. Error Line: '  + CAST(@ErrorLine AS VARCHAR)
                                            + '. Error Message: ' + @ErrorMessage
                        + ' Error Number: ' + CAST(@ErrorNumber AS VARCHAR)
                    + '. Error Severity: ' + CAST(@ErrorSeverity AS VARCHAR)
                        + '. Error State: ' + CAST(@ErrorState AS VARCHAR)
                        + '. Database Name: '  + @DatabaseName
                    + '. Server Name: ' + @ServerName

    IF (XACT_STATE() <> 0)
        BEGIN
           ROLLBACK TRANSACTION 
        END
 
    IF (@ErrorSeverity = 16) AND (@ErrorState = 2)
        BEGIN 
           RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState)
        END      
     ELSE 
        BEGIN 
           -- Log the critical error.   
           BEGIN TRY
              EXEC dbo.InsertBlogErrorLog
                @a_LogDateTime = @CurrentDateTime,    
                @a_UserName = @a_UserName,     
                @a_UserIpAddress = @a_IpAddress,                     
                @a_ObjectID = @@PROCID,
                @a_MessageType = 'S/P Critical Error',
                @a_LogMessage = @ErrorDescription            
           END TRY

           BEGIN CATCH
              -- Stack the messages.
              SELECT @Message = 'Critical Error - procedure InsertBlogErrorLog failed. A log entry cannot be made. Do not continue. Contact IT. Initial error message: ' + @ErrorMessage
              RAISERROR(@Message, 16, 1) 
           END CATCH

           SELECT @message = 'Critical Error - do not continue. Contact IT and provide this log date: ' + Convert(VARCHAR, @CurrentDateTime,21)
           RAISERROR(@Message, 16, 1)                 
        END

     -- Returns failure.
     RETURN 1      

END CATCH
END

Dan...我把我原来的 C# 循环代码放回去,我改变了失败的 s/p GetBlogCategorysInBlogsPublished 我完全删除了 SELECT DISTINCT 子句并通过设置 @Rowcount = 0 来强制 RAISERROR。TRY CATCH 在web api 函数将其拾取并正确处理。

然后,我在 SSMS 中使用了 SELECT DISTINCT 并运行了它。 在结果选项卡中,我看到我得到 2 个结果,列标题和错误消息列。

这两个结果会是问题吗?

在“消息”选项卡中,我得到:Msg 50000, Level 16, State 1, Line 26 严重错误 - 过程 GetBlogCategorysInBlogsPublished 在选择期间失败。没有 BlogCategory 条目。

然后我在 SSMS 中,在没有 SELECT 的情况下强制出错。 在“结果”选项卡中,我看到只有 1 列。

【问题讨论】:

  • 我不知道,但可能是因为 RAISEERROR 没有结束批处理吗?看起来,THROW 确实是 SQL Server 2012 及更高版本中的首选调用:Differences Between RAISERROR and THROW in Sql Server
  • 如果你在设置userFriendlyMessage的值后把throw new Exception(userFriendlyMessage);放在行上,是不是这样?只是为了确保异常不会在其他地方消失。

标签: c# asp.net sql-server asp.net-mvc


【解决方案1】:

确保使用数据访问层中的所有结果集以确保引发异常。使用NextResult()的示例模式:

do {
    while (blogCategoryDataReader.Read())
    {
        blogCategoryList.Add(new BlogCategory
        {
            BlogCategoryId = Convert.ToInt32(blogCategoryDataReader["BlogCategoryId"]),
            BlogCategoryDescr = blogCategoryDataReader["BlogCategoryDescr"].ToString(),
                });
            }
} while blogCategoryDataReader.NextResult();

原因是生成的异常消息RAISERROR在底层表格数据流中SELECT查询生成的结果集后面。这实际上变成了客户端 API 必须使用的多个结果集,因此客户端应用程序必须将所有结果使用到 ensure exceptions are raised and can be detected

请注意,SSMS 使用 FireInfoMessagesOnUserErrors 连接属性而不是 try/catch 来显示用户错误以及其他上下文信息。

【讨论】:

  • 丹..这工作。但奇怪的是,我有这种类似的代码结构抛弃了我的 web api 数据访问层,除了这个之外它们都可以正常工作。在我的 2 个示例中,一个确实有效的示例中,它的存储过程只是执行了一个简单的选择,而失败的示例执行了 Select distinct 并加入。我不明白是什么让它表现得这样。
  • 我认为 select 语句的复杂性并不重要。在读取结果之前不会引发后续错误。尝试使用 CREATE PROC dbo.ErrorHandlingTest AS BEGIN TRY SELECT 1/0 AS oops; END TRY BEGIN CATCH THROW; END CATCH; 之类的最小 proc 进行测试
  • Dan,我将尝试使用最小的 proc,但上面的 2 个示例显示 1 工作正常(因此我强制出错 - 最小测试)和另一个(从不存在行的表中选择)。所以,我基本上已经尝试了2个测试用例。
  • Dan,我把我原来的 C# 循环代码放回去了,我改变了失败的 s/p GetBlogCategorysInBlogsPublished 我完全删除了 SELECT DISTINCT 子句,只是通过设置 @Rowcount = 0 来强制 RAISERROR。TRY CATCH 将其拾取并正确处理。所以一定是Select SELECT DISTINCT。然后我在 SSMS 中创建测试。它们包含在上面以供审核。
  • Dan...所以现在我明白了您在解决方案代码中所说的内容。在我的测试用例中,我可以看到我得到了 2 个结果,而我的 C# 循环代码只看到了第一个结果,没有看到第二个结果,即 raiseerror。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 2012-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多