捕获DbUpdateException后判断是否为唯一约束验证错误的代码问题排查
代码存在的问题及修正
你的代码主要有以下几个问题:
空引用风险未处理:用
as转换InnerException为SqlException时,若转换失败(比如InnerException不是SqlException类型),sqlException会为null,此时直接访问sqlException.Number会抛出NullReferenceException。未遍历完整异常链:
DbUpdateException的InnerException可能不是直接的SqlException,中间可能存在多层包装异常(比如Entity Framework相关的层级异常),必须递归遍历整个InnerException链条,才能定位到真正的SqlException。未限定目标异常类型:参数接收的是通用
Exception,但你实际要处理的是DbUpdateException,传入其他类型异常时逻辑会失效,还可能引发错误。
修正后的代码示例
public static bool IsExceptionUniqueConstraintViolation(Exception ex) { // 先筛选出DbUpdateException var dbUpdateEx = ex as DbUpdateException; if (dbUpdateEx == null) return false; // 遍历异常链查找SqlException var currentEx = dbUpdateEx.InnerException; while (currentEx != null) { if (currentEx is SqlException sqlEx) { // 2601对应唯一索引重复,2627对应唯一约束重复 return sqlEx.Number == 2601 || sqlEx.Number == 2627; } currentEx = currentEx.InnerException; } return false; }
补充说明
- 遍历异常链确保不会遗漏深层的
SqlException; - 先判断
DbUpdateException类型,缩小处理范围,避免无效逻辑; - 使用模式匹配
currentEx is SqlException sqlEx更安全,直接规避空引用问题; - 若使用C# 9及以上版本,可简化条件为
return sqlEx.Number is 2601 or 2627;。
内容的提问来源于stack exchange,提问作者Musa AKYUZ
相关产品推荐
相关产品推荐

