I have this simple .Net Core controller that is supposed to do a DELETE action:
[HttpDelete("{id}")]
public async Task<ActionResult<StudentGrades>> DeleteStudentGrades(string id)
{
var studentGrades = await _context.StudentGrades.FindAsync(id);
if(_context.StudentGrades.Any())
{
_context.StudentGrades.Remove(studentGrades);
await _context.SaveChangesAsync(); // sometimes this throws an error
}
return studentGrades;
}
Sometimes, it will throw this error on this line await _context.SaveChangesAsync();
:
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
But I don't understand why it's throwing that error since I am first checking to make sure that there are studentGrades to remove with _context.StudentGrades.Any()
.
Is there another check I need to do?
Thanks!
CodePudding user response:
The problem occurs when there are student grades in your database, but the one you are trying to delete does not exist.
In your if statement you are checking if any item exists in your database. The solution is to check if the item you are searching for does exist.
A solution would be:
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteStudentGrades(string id)
{
var studentGrades = await _context.StudentGrades.FindAsync(id);
// Check if the student grade was found
if(studentGrades is not null)
{
// Delete the student grade
_context.StudentGrades.Remove(studentGrades);
await _context.SaveChangesAsync();
// Return 200
return Ok();
}
// Student grade not found
return NotFound();
}
CodePudding user response:
You find the entity by its id, then you check if the entire table contains atleast one entry. You forgot your predicate most likely, change:
_context.StudentGrades.Any()
to
_context.StudentGrades.Any(c => c.id == id)
Now this code actually checks if the table has a row with that id, rather than that table having any entries.
Ofcourse this is a bit redundant since you're already fetching the entire entity with your FindAsync(id) call.
Better code would be:
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteStudentGrades(string id, cancellationToken ctx)
{
var studentGrades = await _context.StudentGrades.FirstOrDefaultAsync(id, ctx);
if(studentGrades != null)
{
_context.StudentGrades.Remove(studentGrade);
await _context.SaveChangesAsync();
return Ok();
}
return NotFound();
}