I have a problem and I tried to solve it a lot, which is when I want to modify the user data by the function EditOrCreateInformation()
this error exception message appears:
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded.
Screenshot of the error is display here
Controller code:
[HttpPost]
public IActionResult EditOrCreateInformation(ApplicationUserVm model, ApplicationUser user)
{
if (ModelState.IsValid)
{
var olddata = context.Users.Where(a => a.Id == user.Id).AsNoTracking().FirstOrDefault();
string oldfilename = olddata.PhotoUrl;
if (model.Photo == null)
{
model.PhotoUrl = oldfilename;
}
if (oldfilename != null)
{
if (model.Photo != null && System.IO.File.Exists(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "PhotoFiles/PhotoProfile", oldfilename)))
{
System.IO.File.Delete(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "PhotoFiles/PhotoProfile", oldfilename));
string PhysicalPath = Path.Combine(Directory.GetCurrentDirectory() "/wwwroot", "PhotoFiles/PhotoProfile/");
// 2) Get File Name
string FileName = Guid.NewGuid() Path.GetFileName(model.Photo.FileName);
// 3) Merge Physical Path File Name
string FinalPath = Path.Combine(PhysicalPath, FileName);
// 4) Save The File As Streams "Data Over Time"
using(var stream = new FileStream(FinalPath, FileMode.Create))
{
model.Photo.CopyTo(stream);
}
model.PhotoUrl = FileName;
}
}
else
{
string PhysicalPath = Path.Combine(Directory.GetCurrentDirectory() "/wwwroot", "PhotoFiles/PhotoProfile/");
// 2) Get File Name
string FileName = Guid.NewGuid() Path.GetFileName(model.Photo.FileName);
// 3) Merge Physical Path File Name
string FinalPath = Path.Combine(PhysicalPath, FileName);
// 4) Save The File As Streams "Data Over Time"
using(var stream = new FileStream(FinalPath, FileMode.Create))
{
model.Photo.CopyTo(stream);
}
model.PhotoUrl = FileName;
}
var obj = mapper.Map < ApplicationUser > (model);
applicationUser.Update(obj);
toastNotification.AddSuccessToastMessage("Your Information Updated successfully");
return RedirectToAction("MyProfile", "Profile", new
{
Area = "Identity"
});
}
return View(model);
}
Repository code:
public ApplicationUser Update(ApplicationUser obj)
{
db.Entry(obj).State = EntityState.Modified;
db.SaveChanges();
return db.Users.Where(a => a.Id == obj.Id).FirstOrDefault();
}
How can I fix this?
I will be very grateful to help me solve this problem.
CodePudding user response:
You have two issues here.
- using
AsNoTracking
- using different
DbContext
First, The AsNoTracking
should be only used on read-only queries aka SELECT
. If you need to UPDATE
the same object, then you should select the object without using AsNoTracking
.
Secondly, Update
method you pass the modified User
object to a different context that does not have the current object's change tracking history. So, when SaveChanges
executed, it won't see any changes; because the object's changes were made in a different context.
so what you need to do is just remove AsNoTracking
and replace these lines :
var obj = mapper.Map < ApplicationUser > (model);
applicationUser.Update(obj);
with this :
olddata.PhotoUrl = model.PhotoUrl;
context.Entry(olddata).State = EntityState.Modified;
db.SaveChanges();