Error message: Attaching an entity of type failed because another entity of the same type already has the same primary key value.
Question: How do I attached an entity in a similar fashion as demonstrated in the AttachActivity method in the code below?
I have to assume the "another entity" part of the error message above refers to an object that exists in memory but is out of scope (??). I note this because the Local property of the DBSet for the entity type I am trying to attach returns zero.
I am reasonably confident the entities do not exist in the context because I step through the code and watch the context as it is created. The entities are added in the few lines immediately following creation of the dbcontext.
Am testing for attached entities as specified here:what is the most reasonable way to find out if entity is attached to dbContext or not?
When looking at locals in the locals window of visual studio I see no entities of type Activity (regardless of ID) except the one I am trying to attach.
The code executes in this order: Try -> ModifyProject -> AttachActivity
Code fails in the AttachActivity at the commented line.
Note the code between the debug comments which will throw if any entities have been added to the context.
private string AttachActivity(Activity activity)
{
string errorMsg = ValidateActivity(activity); // has no code yet. No. It does not query db.
if(String.IsNullOrEmpty(errorMsg))
{
// debug
var state = db.Entry(activity).State; // Detached
int activityCount = db.Activities.Local.Count;
int projectCount = db.Activities.Local.Count;
if (activityCount > 0 || projectCount > 0)
throw new Exception("objects exist in dbcontext");
// end debug
if (activity.ID == 0)
db.Activities.Add(activity);
else
{
db.Activities.Attach(activity); // throws here
db.Entry(activity).State = System.Data.Entity.EntityState.Modified;
}
}
return errorMsg;
}
public int ModifyProject(Presentation.PresProject presProject, out int id, out string errorMsg)
{
// snip
foreach (PresActivity presActivity in presProject.Activities)
{
Activity a = presActivity.ToActivity(); // returns new Activity object
errorMsg = ValidateActivity(a); // has no code yet. No. It does not query db.
if (String.IsNullOrEmpty(errorMsg))
{
a.Project = project;
project.Activities.Add(a);
AttachActivity(a);
}
else
break;
}
if (string.IsNullOrEmpty(errorMsg))
{
if (project.ID == 0)
db.Projects.Add(project);
else
db.AttachAsModfied(project);
saveCount = db.SaveChanges();
id = project.ID;
}
return saveCount;
}
This is the class that news up the dbContext:
public void Try(Action<IServices> work)
{
using(IServices client = GetClient()) // dbContext is newd up here
{
try
{
work(client); // ModifyProject is called here
HangUp(client, false);
}
catch (CommunicationException e)
{
HangUp(client, true);
}
catch (TimeoutException e)
{
HangUp(client, true);
}
catch (Exception e)
{
HangUp(client, true);
throw;
}
}
I am not asking: How do I use AsNoTracking What difference does .AsNoTracking() make?