.NET 4.6.1应用遇Azure SQL维护断连时如何实现重试机制?
一、明确内置重试的局限
你之前配置的ConnectRetryCount和ConnectRetryInterval仅作用于首次建立数据库连接的场景,无法覆盖长进程中已连接后因Azure SQL维护导致的连接中断——这就是测试后仍报错的核心原因。.NET 4.6.1原生System.Data.SqlClient没有内置命令级重试机制,必须通过扩展实现全局重试,且无需修改数百处业务代码。
二、最优实现方案:基于Microsoft.Data.SqlClient的全局重试
1. 替换SqlClient组件
通过NuGet安装Microsoft.Data.SqlClient包(.NET 4.6.1兼容对应版本),替换项目中所有System.Data.SqlClient的引用——该替换几乎无代码侵入,API完全兼容原有逻辑。
2. 全局配置自定义退避重试策略
仅需在应用启动时(如Global.asax、Program.cs入口)初始化一次,后续所有数据库操作自动应用该策略,无需修改业务代码:
using Microsoft.Data.SqlClient; using Microsoft.Data.SqlClient.RetryLogic; // 初始化自定义重试选项:按需求配置递增间隔(30s→1min→5min→10min→30min→60min) var retryOptions = new SqlRetryLogicOption() { NumberOfTries = 6, // 自定义固定递增间隔数组,单位秒 CustomRetryInterval = new TimeSpan[] { TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(60) }, // 若需指数退避(间隔翻倍),可替换为以下配置: // RetryType = SqlRetryType.ExponentialBackoff, // DeltaTime = TimeSpan.FromSeconds(30), // MaxTimeInterval = TimeSpan.FromMinutes(60), // 定义需要重试的异常类型:覆盖Azure SQL维护、断连、超时等场景 TransientErrors = new List<int> { 4060, // 无法打开指定数据库 10928, // Azure SQL实例资源不足 10929, // Azure SQL实例资源不足 40197, // 服务重启中 40501, // 服务繁忙 40613, // 数据库暂不可用 10053, // 传输级连接错误 10054, // TCP连接被重置 10060, // 连接超时 -2 // 通用执行超时 } }; // 创建重试提供者并全局注册 var retryProvider = new SqlRetryLogicProvider(retryOptions); SqlConnection.RetryLogicProvider = retryProvider;
3. 验证效果
用你之前的测试方法(手动离线数据库、断网),长进程中的数据库操作会自动按配置的间隔重试,直到达到最大次数后才抛出异常——完全不需要修改业务代码里的SqlCommand、SqlDataReader等逻辑。
三、无需修改数百处代码的核心逻辑
通过全局注册SqlRetryLogicProvider,所有SqlConnection实例都会自动应用重试策略,包括原有代码中通过连接字符串创建的连接——相当于在ADO.NET底层拦截命令执行,统一处理重试逻辑。
四、替代方案(不替换SqlClient包)
若无法替换Microsoft.Data.SqlClient,可封装一个全局的DbConnection包装类,在ExecuteNonQuery、ExecuteReader等核心方法中添加自定义重试逻辑,再将项目中所有创建连接的地方替换为该包装类实例。但这种方式侵入性稍高,不如前者简洁。
内容的提问来源于stack exchange,提问作者ysi_d

