时间:2021-07-01 10:21:17 帮助过:72人阅读
services.AddDbContext<CnblogsDbContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("cnblogs"), builder => { builder.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); }); });
但是测试发现不起作用。
期望的测试结果是这样的:启动 asp.net core 站点 -> curl 发请求 -> 正常响应 -> 停止 SQL Server 服务器 -> curl 发请求 -> 等待 -> 30秒之后启动 SQL Server -> 正常响应。
实际的测试结果却是这样:启动 asp.net core 站点 -> curl 发请求 -> 正常响应 -> 停止 SQL Server 服务器 -> curl 发请求 -> 15秒左右出现500错误,报上面的异常。
难道这个异常不在 RetryOnFailure 的默认范围?
于是通过 errorNumbersToAdd 添加 0x80131904 错误码:
var errorNumer = 0x80131904; builder.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: new int[] { (int)errorNumer });
却依然不起作用。
别无他法,只能硬啃 EFCore 的源代码找线索了,于是找到 SqlServerTransientExceptionDetector
public class SqlServerTransientExceptionDetector { public static bool ShouldRetryOn([NotNull] Exception ex) { if (ex is SqlException sqlException) { foreach (SqlError err in sqlException.Errors) { switch (err.Number) { case 49920: case 49919: case 49918: case 41839: case 41325: case 41305: case 41302: case 41301: case 40613: case 40501: case 40197: case 10929: case 10928: case 64: case 20: } } return false; } if (ex is TimeoutException) { return true; } return false; } }
原来是根据 SqlError.Number 来判断的, 上面的数字都这么小,看来 0x80131904 不是 SqlError.Number ,再次查看错误日志发现在 System.Data.SqlClient.SqlException (0x80131904) 之前有下面一行日志:
Error Number:2,State:0,Class:20
原来是 2 ,于是在 errorNumbersToAdd 中添加这个 error number ,问题就解决了。
services.AddDbContext<CnblogsDbContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("cnblogs"), builder => { builder.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: new int[] { 2 }); }); });
使用 EF Core 的 EnableRetryOnFailure 解决短暂的数据库连接失败问题
标签:not found state erro logs cond 默认 查看 sys blog