如何在EF Core中复现SQL Server时态表更新错误并验证修复方案
在EF Core里复现系统版本表并行更新错误&验证重试修复方案
一、怎么模拟EF Core并行更新场景
EF Core的DbContext不是线程安全的,不能多个线程共用一个实例,但每个线程单独创建DbContext实例就能模拟并行操作,这是核心操作:
- 先插入一条测试用的Invoice数据,让多个线程能同时修改它
- 用
Parallel.ForEach或者Task.WhenAll启动一批并行任务,每个任务里执行以下操作:- 新建一个独立的DbContext实例
- 查询到目标Invoice记录
- 修改任意非
UpdatedDate的字段(比如Amount) - 调用
SaveChangesAsync提交更改
示例代码:
// 提前插入测试数据 using (var initContext = new InvoiceDbContext()) { var testInvoice = new Invoice { Id = 1, Amount = 100, UpdatedDate = DateTime.Now }; initContext.Invoices.Add(testInvoice); initContext.SaveChanges(); } // 模拟并行更新 var tasks = Enumerable.Range(0, 10).Select(_ => Task.Run(async () => { using (var context = new InvoiceDbContext()) { var invoice = await context.Invoices.FindAsync(1); invoice.Amount += 10; // 任意更新字段即可 try { await context.SaveChangesAsync(); Console.WriteLine("更新成功"); } catch (DbUpdateException ex) { if (ex.InnerException is SqlException sqlEx && sqlEx.Number == 13585) // 对应目标错误的SQL官方错误码 { Console.WriteLine("触发目标错误:" + sqlEx.Message); } else { throw; } } } })); await Task.WhenAll(tasks);
二、验证重试修复方案
你提到的启用重试机制的EF Core配置,需要精准针对SqlException 13585错误添加重试规则。
配置示例(可放在Program.cs或DbContext配置逻辑中):
builder.Services.AddDbContext<InvoiceDbContext>(options => options.UseSqlServer(connectionString, sqlOptions => { sqlOptions.EnableRetryOnFailure( maxRetryCount: 5, // 最大重试次数 maxRetryDelay: TimeSpan.FromSeconds(1), // 每次重试间隔 errorNumbersToAdd: new[] { 13585 }); // 加入目标错误码 }));
验证步骤:
- 运行上述并行测试代码
- 观察控制台输出,确认错误被捕获并触发重试,最终部分更新操作成功完成
- 检查数据库中的Invoice记录,确认最终数据符合预期(比如10次更新后Amount应为200,重试成功则结果正确)
关键注意事项
- 必须保证每个线程使用独立的DbContext实例,避免线程安全问题
- 确保SQL Server系统版本表配置正确:
UpdatedDate设置为GETDATE(),周期字段配置无误 - 错误码13585是SQL Server对应该系统版本表错误的官方编码,务必准确加入重试列表
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

