ASP.NET Core MVC+Angular CRUD更新报错DbUpdateConcurrencyException求解
问题:ASP.NET Core MVC + Angular CRUD 更新记录失败,报DbUpdateConcurrencyException
使用ASP.NET Core MVC结合Angular开发CRUD系统,新增、删除、查看功能均正常,但更新记录时失败,报错信息如下:
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:
The database operation was expected to affect 1 row(s), but actually affected 0 row(s);
后端代码(StudentController.cs)
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using ReactAspCrud.Models; namespace ReactAspCrud.Controllers { [Route("api/[controller]")] [ApiController] public class StudentController : ControllerBase { private readonly StudentDbContext _studentDbContext; public StudentController(StudentDbContext studentDbContext) { _studentDbContext = studentDbContext; } [HttpGet] [Route("GetStudent")] public async Task<IEnumerable<Student>> GetStudents() { return await _studentDbContext.Student.ToListAsync(); } [HttpPost] [Route("AddStudent")] public async Task<Student> AddStudent(Student objStudent) { _studentDbContext.Student.Add(objStudent); await _studentDbContext.SaveChangesAsync(); return objStudent; } [HttpPatch] [Route("UpdateStudent/{id}")] public async Task<Student> UpdateStudent(Student objStudent) { _studentDbContext.Entry(objStudent).CurrentValues.SetValues(objStudent); _studentDbContext.Entry(objStudent).State= EntityState.Modified; await _studentDbContext.SaveChangesAsync(); return objStudent; } [HttpDelete] [Route("DeleteStudent/{id}")] public bool DeleteStudent(int id) { bool a = false; var student = _studentDbContext.Student.Find(id); if (student != null) { a = true; _studentDbContext.Entry(student).State= EntityState.Deleted; _studentDbContext.SaveChanges(); } else { a = false; } return a; } } }
前端代码(Studentcrud.components.ts)
setUpdate(data: any) { this.stname = data.stname; this.course = data.course; this.currentStudentID = data.id; } UpdateRecords() { let bodyData = { "stname" : this.stname, "course" : this.course, }; this.http.patch("https://localhost:7195/api/Student/UpdateStudent"+ "/"+ this.currentStudentID,bodyData).subscribe((resultData: any)=> { console.log(resultData); alert("Student Registered Updateddd") this.getAllStudent(); }); }
问题原因及修复方案
核心问题
- 后端
UpdateStudent方法定义了路由参数{id},但方法未接收该参数,也没有通过主键从数据库查询目标实体,直接修改未被EF Core追踪的对象,导致无法定位数据库中的记录。 - 前端请求的Body中未包含
id字段,后端接收的Student对象主键为空,EF Core找不到要更新的行。
修复步骤
后端修改(推荐方案)
先通过路由参数id查询数据库中的实体,再更新指定字段,最后保存变更:
[HttpPatch] [Route("UpdateStudent/{id}")] public async Task<IActionResult> UpdateStudent(int id, Student objStudent) { var existingStudent = await _studentDbContext.Student.FindAsync(id); if (existingStudent == null) { return NotFound("学生记录不存在"); } // 更新需要修改的字段 existingStudent.stname = objStudent.stname; existingStudent.course = objStudent.course; await _studentDbContext.SaveChangesAsync(); return Ok(existingStudent); }
前端可选优化
如果需要保持后端直接接收完整实体的方式,可在请求Body中加入id字段:
UpdateRecords() { let bodyData = { "id": this.currentStudentID, "stname" : this.stname, "course" : this.course, }; this.http.patch(`https://localhost:7195/api/Student/UpdateStudent/${this.currentStudentID}`, bodyData).subscribe((resultData: any)=> { console.log(resultData); alert("学生记录更新成功") this.getAllStudent(); }); }
内容的提问来源于stack exchange,提问作者abi jega
相关产品推荐
相关产品推荐

