.NET Core控制器已做实体存在检查仍报错,原因何在?
你的代码里有两个关键问题导致了这个错误:
1. 错误的存在性检查
_context.StudentGrades.Any()只是判断整个StudentGrades表是否有数据,完全不针对你要删除的id对应的记录。哪怕表不为空,这个判断也无法验证你通过FindAsync获取的studentGrades是否有效——比如在FindAsync执行后、Any()检查前,这条记录已经被其他操作删除,此时studentGrades会是null,但Any()仍会返回true,最终导致删除null实体或执行SaveChanges时报错。
2. 未处理并发删除/修改场景
即使你成功通过FindAsync获取到了记录,在调用Remove到SaveChangesAsync的这段时间里,这条记录可能被其他请求或进程删除/修改。EF Core执行删除操作时会检查数据库中是否存在目标记录,发现不存在就会抛出DbUpdateConcurrencyException。
修正方案
第一步:替换无效检查,先验证查询结果
把if(_context.StudentGrades.Any())改成直接检查studentGrades是否为null,确保要删除的记录确实存在:
[HttpDelete("{id}")] public async Task<ActionResult<StudentGrades>> DeleteStudentGrades(string id) { var studentGrades = await _context.StudentGrades.FindAsync(id); if (studentGrades == null) { return NotFound(); // 记录不存在,直接返回404 } _context.StudentGrades.Remove(studentGrades); try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { // 捕获并发异常后,重新查询数据库确认记录状态 if (!_context.StudentGrades.Any(sg => sg.Id == id)) { return NotFound(); // 记录已被其他操作删除,返回404 } else { // 记录存在但被修改,根据业务需求返回冲突提示或其他响应 return Conflict("该记录已被其他操作修改,删除失败"); } } return studentGrades; }
第二步:理解并发处理逻辑
- 捕获
DbUpdateConcurrencyException后必须重新查询数据库,因为之前的studentGrades是内存中的旧数据,无法反映当前数据库的真实状态。 - 如果重新查询后记录不存在,说明是并发删除场景;如果存在,则是并发修改场景,可根据业务需求选择返回冲突提示、重试删除或其他处理方式。
可选:使用并发令牌优化并发控制
如果你的业务需要更严格的并发校验,可以给StudentGrades实体添加RowVersion属性(SQL Server对应timestamp类型),EF Core会自动用它检测并发修改:
public class StudentGrades { public string Id { get; set; } // 其他业务属性... [Timestamp] public byte[] RowVersion { get; set; } }
添加后,EF Core执行删除时会自动对比数据库中的RowVersion值与内存中的值,不一致则抛出并发异常,能更精准地检测到并发修改场景。
内容的提问来源于stack exchange,提问作者SkyeBoniwell
相关产品推荐
相关产品推荐

