When i tried to edit an object i got the following error :-
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
My POSTEdit action method that causes the problme looks as follow:-
[HttpPost]
public ActionResult Edit(Visit visit)
{ try
{
if (ModelState.IsValid)
{
var p = repository.GetVisit(visit.VisitID);
visit.CreatedBy = p.CreatedBy;
visit.Date = p.Date;
visit.PatientID = p.PatientID;
if (!((visit.EditableByAssingedDoctor(User.Identity.Name)) || (visit.EditableByCreatedBy(User.Identity.Name))))
{
return View("NotFound");
}
repository.UpdateVisit(visit);
repository.Save();
return RedirectToAction("Index");
}
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var clientValues = (Visit)entry.Entity;
ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again. Otherwise click the Back to List hyperlink.");
}
//code foes here
the above repository.UpdateVisit(visit); (inside the action method) code looks as follow:-
public void UpdateVisit(Visit v)
{ entities.Entry(v).State = EntityState.Modified; }
But when i try to update the object i got the following error "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key."
on the repository.UpdateVisit(visit). so what might be the problme?
Hint:- i am currently retriving the values from the database for the (CreatedBy, Date , PatientID) fields and then i am assinging them to the object before saving the changies; to prevent any attacker from modifying their values during the Edit operation.
You cannot have two entities with the same key in ObjectStateManager. In your case p and visit have the same EntityKey and you need to detach p before you can attach visit:
var p = repository.GetVisit(visit.VisitID);
visit.CreatedBy = p.CreatedBy;
visit.Date = p.Date;
visit.PatientID = p.PatientID;
if (!((visit.EditableByAssingedDoctor(User.Identity.Name)) || (visit.EditableByCreatedBy(User.Identity.Name))))
{
return View("NotFound");
} //detach p from context here...
repository.UpdateVisit(visit);
repository.Save();
return RedirectToAction("Index");
thanks a lot for your help it was really helpfull, i have updated my action method to the following ,, and i added an new repository method for detaching the object as below:-
[HttpPost]
public ActionResult Edit(Visit visit) //[Bind(Include="Note,DoctorID,VisitID,StatusID")]
{ try
{
if (ModelState.IsValid)
{var p = repository.GetVisit(visit.VisitID);
visit.CreatedBy = p.CreatedBy;
visit.Date = p.Date;
visit.PatientID = p.PatientID;
if (!((visit.EditableByAssingedDoctor(User.Identity.Name)) || (visit.EditableByCreatedBy(User.Identity.Name))))
{
return View("NotFound");
}
repository.Detach(p);
repository.UpdateVisit(visit);
repository.Save();
return RedirectToAction("Index");
}
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var clientValues = (Visit)entry.Entity;
ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again. Otherwise click the Back to List hyperlink.");
}
and the following two repository methods:-
public void Detach (Visit v) {
((IObjectContextAdapter)entities).ObjectContext.Detach(v);
}
public void UpdateVisit(Visit v)
{
entities.Entry(v).State = EntityState.Modified;
}
I tested my the above appraoch and it worked fine in both ; 1. it is raising the DbUpdateConcurrencyException when it should do ,
2. and also it is assigning the old values for both the (Date, CreatedBy, PatientID) as required.
So is there any thing i should add that i am unaware of as this is the first time i have wrote similar functionality?.
. it is raising the DbUpdateConcurrencyException when it should do
To raise this exception,you should set a TimeStamp field in your database;and when the timestamps occurs concurrency,the exception will be thrown out。
johnjohn123123
and also it is assigning the old values for both the (Date, CreatedBy, PatientID) as required.
If you want to get the original object instance,just do that through the exception:
var entry = ex.Entries.Single(); var databaseValues = (YourModelEntity)entry.GetDatabaseValues().ToObject(); var clientValues = (YourCurrentModelEntity)entry.Entity;
johnjohn1231...
Participant
922 Points
871 Posts
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cann...
May 04, 2012 11:55 PM|LINK
When i tried to edit an object i got the following error :- An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
My POSTEdit action method that causes the problme looks as follow:-
[HttpPost] public ActionResult Edit(Visit visit) { try { if (ModelState.IsValid) { var p = repository.GetVisit(visit.VisitID); visit.CreatedBy = p.CreatedBy; visit.Date = p.Date; visit.PatientID = p.PatientID; if (!((visit.EditableByAssingedDoctor(User.Identity.Name)) || (visit.EditableByCreatedBy(User.Identity.Name)))) { return View("NotFound"); } repository.UpdateVisit(visit); repository.Save(); return RedirectToAction("Index"); } } catch (DbUpdateConcurrencyException ex) { var entry = ex.Entries.Single(); var clientValues = (Visit)entry.Entity; ModelState.AddModelError(string.Empty, "The record you attempted to edit " + "was modified by another user after you got the original value. The " + "edit operation was canceled and the current values in the database " + "have been displayed. If you still want to edit this record, click " + "the Save button again. Otherwise click the Back to List hyperlink."); } //code foes herethe above repository.UpdateVisit(visit); (inside the action method) code looks as follow:-
public void UpdateVisit(Visit v) { entities.Entry(v).State = EntityState.Modified; }But when i try to update the object i got the following error "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key." on the repository.UpdateVisit(visit). so what might be the problme?
Hint:- i am currently retriving the values from the database for the (CreatedBy, Date , PatientID) fields and then i am assinging them to the object before saving the changies; to prevent any attacker from modifying their values during the Edit operation.
BR
mm10
Contributor
6395 Points
1182 Posts
Re: An object with the same key already exists in the ObjectStateManager. The ObjectStateManager ...
May 05, 2012 09:17 AM|LINK
You cannot have two entities with the same key in ObjectStateManager. In your case p and visit have the same EntityKey and you need to detach p before you can attach visit:
var p = repository.GetVisit(visit.VisitID);
visit.CreatedBy = p.CreatedBy;
visit.Date = p.Date;
visit.PatientID = p.PatientID;
if (!((visit.EditableByAssingedDoctor(User.Identity.Name)) || (visit.EditableByCreatedBy(User.Identity.Name))))
{
return View("NotFound");
}
//detach p from context here...
repository.UpdateVisit(visit);
repository.Save();
return RedirectToAction("Index");
johnjohn1231...
Participant
922 Points
871 Posts
Re: An object with the same key already exists in the ObjectStateManager. The ObjectStateManager ...
May 05, 2012 04:30 PM|LINK
thanks a lot for your help it was really helpfull, i have updated my action method to the following ,, and i added an new repository method for detaching the object as below:-
[HttpPost] public ActionResult Edit(Visit visit) //[Bind(Include="Note,DoctorID,VisitID,StatusID")] { try { if (ModelState.IsValid) {var p = repository.GetVisit(visit.VisitID); visit.CreatedBy = p.CreatedBy; visit.Date = p.Date; visit.PatientID = p.PatientID; if (!((visit.EditableByAssingedDoctor(User.Identity.Name)) || (visit.EditableByCreatedBy(User.Identity.Name)))) { return View("NotFound"); } repository.Detach(p); repository.UpdateVisit(visit); repository.Save(); return RedirectToAction("Index"); } } catch (DbUpdateConcurrencyException ex) { var entry = ex.Entries.Single(); var clientValues = (Visit)entry.Entity; ModelState.AddModelError(string.Empty, "The record you attempted to edit " + "was modified by another user after you got the original value. The " + "edit operation was canceled and the current values in the database " + "have been displayed. If you still want to edit this record, click " + "the Save button again. Otherwise click the Back to List hyperlink."); }and the following two repository methods:-
public void Detach (Visit v) { ((IObjectContextAdapter)entities).ObjectContext.Detach(v); } public void UpdateVisit(Visit v) { entities.Entry(v).State = EntityState.Modified; }I tested my the above appraoch and it worked fine in both ; 1. it is raising the DbUpdateConcurrencyException when it should do , 2. and also it is assigning the old values for both the (Date, CreatedBy, PatientID) as required. So is there any thing i should add that i am unaware of as this is the first time i have wrote similar functionality?.
BR
Decker Dong ...
All-Star
118619 Points
18779 Posts
Re: An object with the same key already exists in the ObjectStateManager. The ObjectStateManager ...
May 07, 2012 01:38 AM|LINK
To raise this exception,you should set a TimeStamp field in your database;and when the timestamps occurs concurrency,the exception will be thrown out。
If you want to get the original object instance,just do that through the exception: