EntityFrameworkCore中SaveChanges操作的弹性重试方案咨询
实现
SaveChanges()的数据库重试弹性能力 有两个开箱即用的方案可以直接解决这个问题,不用自己写大量重复维护的代码:
1. EF Core 内置重试机制
这是最省心的方案,官方原生支持,专门针对EF Core的数据库操作优化,覆盖了常见的瞬态错误(比如数据库临时宕机、连接中断、死锁)。
配置方式很简单,在注册DbContext的时候开启重试即可:
services.AddDbContext<YourDbContext>(options => { options.UseSqlServer("你的数据库连接字符串", sqlOpts => sqlOpts.EnableRetryOnFailure( maxRetryCount: 3, // 最大重试次数 maxRetryDelay: TimeSpan.FromSeconds(5), // 每次重试的最大延迟 errorNumbersToAdd: new[] { 4060, 10928, 10929 } // 可选:添加需要重试的特定SQL Server错误码 )); });
配置后,所有SaveChanges()、SaveChangesAsync()调用都会自动触发重试,无需修改业务代码。
2. Polly 通用弹性库
如果需要更灵活的重试策略(比如结合熔断、指数退避、自定义错误判断),可以用Polly这个成熟的.NET弹性库。
首先安装Polly包,然后定义重试策略并包裹SaveChanges()调用:
// 定义针对数据库瞬态错误的重试策略 var dbRetryPolicy = Policy .Handle<DbUpdateException>(ex => IsTransientDatabaseError(ex)) .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // 指数退避重试 // 调用SaveChanges时应用策略 dbRetryPolicy.Execute(() => context.SaveChanges());
辅助方法用于判断是否为瞬态错误:
private bool IsTransientDatabaseError(DbUpdateException ex) { if (ex.InnerException is SqlException sqlEx) { // 匹配SQL Server常见的瞬态错误码 return sqlEx.Errors.Cast<SqlError>().Any(error => error.Number is 4060 or 10928 or 10929 or 40197 or 40501); } return false; }
选择建议
- 如果你用的是EF Core,优先用内置重试,零额外依赖,配置简单。
- 如果需要跨场景的弹性策略(比如同时处理HTTP调用和数据库操作),或者需要高度自定义重试逻辑,选Polly。
内容的提问来源于stack exchange,提问作者Ph3n0m
相关产品推荐
相关产品推荐

