I have editing data with entry method in ef core inside an async method. but when the program reaches the entry method throws an exception. exception message :
System.InvalidOperationException: 'The instance of entity type
'clinicSpecifications' cannot be tracked because another instance with the same key value for {'clinicSpecificationsID'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.'
this is my action:
[HttpPost("updateClinicSpecifications")]
public async Task<IActionResult> updateData(clinicSpecifications clinicSpecificationsParam, clinicOpeningHours clinicOpeningHoursParam)
{
if (clinicSpecificationsParam.isActive == true)
{
await ClinicSpecificationsRepository.disableAllClinicAddress();
//update AllAddress To Disable this update working correctly
await ClinicSpecificationsRepository.saveChanges();
}
clinicSpecificationsParam.createDate = DateTime.Now.toShamsi();
clinicOpeningHoursParam.createDate = DateTime.Now.toShamsi();
//but when program reaches to this update exception is throws
bool result = await ClinicSpecificationsRepository.editclinicSpecifications(clinicSpecificationsParam);
bool result2 = await ClinicOpeningHoursRepository.editClinicOpeningHours(clinicOpeningHoursParam);
if (result == true)
{
await ClinicSpecificationsRepository.saveChanges();
}
if (result2 == true)
{
await ClinicOpeningHoursRepository.saveChanges();
}
return RedirectToAction("Index");
}
this is disableAllClinicAddress method :
public async Task disableAllClinicAddress()
{
var allAddress = await getAllClinicSpecifications();
foreach (var item in allAddress)
{
item.isActive = false;
await editclinicSpecifications(item);
}
}
and my update method :
public async Task<bool> editclinicSpecifications(clinicSpecifications clinicSpecifications)
{
try
{
await Task.Run(() => db.Entry(clinicSpecifications).State = EntityState.Modified);
return true;
}
catch (Exception)
{
return false;
}
}
please help me thanks.
I have editing data with entry method in ef core inside an async method. but when the program reaches the entry method throws an exception. exception message
Because you're creating a new instance (which isn't tracked) instead of updating the existing instance (which is tracked).Change like below:
var clinicSpecificationsParam = _dbcontext.clinicSpecifications.Find(id);
Here is a working demo I tested:
1.Model:
public class clinicSpecifications
{
public int Id { get; set; }
public bool isActive { get; set; }
public DateTime createDate { get; set; }
}
2.Controller:
public class HomeController : Controller
{
private readonly YourContext _context;
public HomeController(YourContext context)
{
_context = context;
}
[HttpPost("updateClinicSpecifications")]
public async Task<IActionResult> updateData(int id)
{
var clinicSpecificationsParam = _context.clinicSpecifications.Find(id);
if (clinicSpecificationsParam.isActive == true)
{
await disableAllClinicAddress();
await _context.SaveChangesAsync();
}
clinicSpecificationsParam.createDate = DateTime.Now;
bool result = await editclinicSpecifications(clinicSpecificationsParam);
//...
return RedirectToAction("Index");
}
public async Task disableAllClinicAddress()
{
var allAddress = _context.clinicSpecifications.ToList();
foreach (var item in allAddress)
{
item.isActive = false;
await editclinicSpecifications(item);
}
}
public async Task<bool> editclinicSpecifications(clinicSpecifications clinicSpecifications)
{
try
{
await Task.Run(() => _context.Entry(clinicSpecifications).State = EntityState.Modified);
return true;
}
catch (Exception)
{
return false;
}
}
3.DbContext:
public class YourContext : DbContext
{
public YourContext (DbContextOptions<YourContext> options)
: base(options)
{
}
public DbSet<clinicSpecifications> clinicSpecifications { get; set; }
}
In your update method, avoid using EntityState.Modified. I know it's a valid command but you can see you are having issues. You must first track the entry in question by doing a find or firstordefault to collect the record. Then you can modify the record and resave it. Here's some code off the top of my head but not tested.
var entry = db.ClinicSpecifications.FirstOrDefault(c => c.Id);
entry.Field = clinicSpecification.Field;
db.SaveChanges();
Again a rough example, but it works flawlessly.