使用Polly WaitAndRetry实现数据库查询重试遇空引用异常求助
问题分析与解决方案
你的代码存在两个核心问题,导致重试逻辑未触发且抛出异常:
重试条件不匹配
当前Polly策略仅捕获Exception,但查询返回null或ID=0属于正常返回(不会抛出异常),因此Polly不会触发重试。返回类型不兼容
ExecuteAsync<BatchMailLog>指定返回BatchMailLog类型,但实际执行的QueryFirstOrDefaultAsync<StageLog>返回StageLog类型,类型不匹配会引发转换异常,也就是你遇到的NullReferenceException。
修正后的代码
var parameters = new { PackageID = packageId }; var query = $"Select ID From Staging..Log Where StagePkg=@PackageID"; // 定义重试策略:捕获异常 + 检查返回结果是否无效 var retryPolicy = Policy .Handle<Exception>() .OrResult<StageLog>(result => result == null || result.ID == 0) // 新增:识别无效返回结果 .WaitAndRetryAsync(4, retryAttempt => { // 调整重试节奏,每次等10秒,总等待40秒匹配数据库生成窗口 var timeToWait = TimeSpan.FromSeconds(10); Console.WriteLine($"等待 {timeToWait.TotalSeconds} 秒后重试"); return timeToWait; }); // 修正返回类型,与查询结果类型保持一致 return await retryPolicy.ExecuteAsync<StageLog>(async () => await SybaseConnection.WithConnectionAsync(c => c.QueryFirstOrDefaultAsync<StageLog>(query, parameters)) );
关键调整说明
- 新增结果校验逻辑:通过
.OrResult<StageLog>(...)让Polly把“返回null”或“ID=0”判定为需要重试的场景。 - 优化重试等待策略:将原指数退避(10秒、100秒...)改为固定10秒重试一次,重试4次总等待40秒,匹配数据库生成数据的35-45秒时间窗口。
- 修正类型匹配问题:将
ExecuteAsync<BatchMailLog>改为ExecuteAsync<StageLog>,避免类型转换异常。如果业务最终需要BatchMailLog,可在获取有效StageLog后再做字段映射。
内容的提问来源于stack exchange,提问作者born2Learn
相关产品推荐
相关产品推荐

