.net之SqlException 转换为自定义异常处理程序

哈哈 阅读:10 2024-02-27 23:08:18 评论:0

我有一个现有的应用程序,它使用 MS SQL 存储过程来执行一些业务规则。当检测到错误时,使用 RAISERROR 将其作为异常返回到我的 .Net 应用程序。

然后 .Net 应用程序可以使用 Try/Catch block 来捕获异常并执行业务逻辑。问题是在单个存储过程中验证了多个业务规则。这可能会引发不同的异常。捕获这些 SQL 异常并将它们转换为自定义 .Net 异常处理程序的最佳方法是什么。

例如,我的存储过程可能会为 RuleA 和 RuleB 抛出异常。在我的 .Net 代码中,我只能捕获 SqlException。我针对 RuleA 或 RuleB 的自定义错误消息在 SqlException 内部异常中返回。我可以解析消息字符串,但这是丑陋的,如果有人更改存储过程中的实现。我的逻辑不会接受它。

将通用 SqlException 转换为 MyRuleAException 或 MyRuleBException 的首选方法是什么?

请您参考如下方法:

通常的做法是在您的 .Net 代码中定义错误常量,然后您可以在异常处理代码中检查该值。您可以使用常量使代码更具可读性,如下所示:

/// <summary> 
/// Represents the error code returned from stored procedure when entity could not be found. 
/// </summary> 
private const int SQL_ERROR_CODE_ENTITY_NOT_FOUND = 50001; 
 
/// <summary> 
/// Represents the error code returned from stored procedure when entity to be updated has time mismatch. 
/// </summary> 
private const int SQL_ERROR_CODE_TIME_MISMATCH = 50002; 
 
/// <summary> 
/// Represents the error code returned from stored procedure when a persistence exception occurs (ex. 
/// billing flag is invalid, child records exist which prevent a delete, etc.). 
/// </summary> 
private const int SQL_ERROR_CODE_PERSISTENCE_ERROR = 50003; 

然后,您可以像这样处理异常,它使您的代码更具可读性和可维护性:

    if (e.InnerException is SqlException) 
    { 
        // verify exception code from SP and throw proper exception if required 
        var sqlException = (SqlException)e.InnerException; 
        if (sqlException.Number == SQL_ERROR_CODE_ENTITY_NOT_FOUND) 
        { 
            e = new EntityNotFoundException(e.Message, e); 
        } 
        else if (sqlException.Number == SQL_ERROR_CODE_TIME_MISMATCH) 
        { 
            e = new EntityTimestampMismatchException(e.Message, e); 
        } 
        else if (sqlException.Number == SQL_ERROR_CODE_PERSISTENCE_ERROR) 
        { 
            e = new EntityServicePersistenceException(e.Message, e); 
        } 
    } 

在我看来,这已经是你所能做到的最干净的了,但它仍然没问题,因为你在一个地方定义了错误代码,所以如果有任何变化,你只需更改一个常量。

要引发错误,您可以在 T-SQL 中执行如下操作:

 -- record wasn't found, raise an error 
 DECLARE @l_error NVARCHAR(1000) 
 SET @l_error = 'Record with ' + @p_IdFieldName + ' = ' + CONVERT(VARCHAR(128), @p_id) 
    + ' does not exist in table [' + @p_TableName + ']' 
 EXEC sp_addmessage @msgnum=50001, @severity=16, @msgtext=@l_error, @replace='replace' 
 RAISERROR(50001, 16, 1) 

50001 表示将在 SqlException.Number 中的错误编号。


标签:Exception
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号