Grizzly
Grizzly

Reputation: 5943

Attaching an entity of type.. failed because

I am experiencing strange behavior with my Edit action on one of my controllers.

Here is my code:

public ActionResult Edit([Bind(Include = "ID,FirstName,LastName,Email,deleted,AId")] Information personInformation)
{

    // to stop multiple calls to database
    var lstOfPeople = db.Information.Where(x => x.deleted == false).ToList();

    if (ModelState.IsValid)
    {

        if (lstOfPeople.Any(x => x.Email.Equals(personInformation.Email, StringComparison.CurrentCultureIgnoreCase) && x.ID != personInformation.ID))
        {
            ModelState.AddModelError("", "This email already exists!");
            return View(personInformation);
        }

        db.Entry(personInformation).State = EntityState.Modified; // error here
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(personInformation);
}

Now I have pretty much the exact same code in a different controller edit action and it works fine. Here that is:

public ActionResult Edit([Bind(Include = "ID,RNumber,DateCreated,PersonWhoCreated,deleted")] OtherTable oTable)
{
    if (ModelState.IsValid)
    {
        if (db.OtherTable.Any(x => x.RNumber.Equals(oTable.RNumber, StringComparison.CurrentCultureIgnoreCase) && x.ID != oTable.ID))
        {
            ModelState.AddModelError("RNumber", "This number already exists!");
            return View(oTable);
        }

        db.Entry(oTable).State = EntityState.Modified; // no error here.. goes through fine.
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(oTable);
}

Error I am receiving:

Attaching an entity of type 'ProjectName.Models.Information' failed because another entity of the same type already has the same primary key value. This can happen when using 'Attach'.. etc.

Any idea on why this is happening?

Upvotes: 1

Views: 682

Answers (1)

animalito maquina
animalito maquina

Reputation: 2414

The db.Entry(personInformation).State attachs the personInformation object to the EF context, the error raises because the EF data context has previously loaded a diferent Information instance with the same id (perhaps in the previous Where() you are doing).

There are at least two basic options:

  • first one is to use the AsNoTracking() extension for your queries, (as in db.Information.AsNoTracking()) this extension tells EF data context to not keep the entities retrieved from database in memory so you can attach your personInformation entity directly to the context and set the modified state.
  • second option is retrieve the entity from the ef data context and modify that entity (not the personInformation instance). You can retrieve the entity with db.Information.FindAsync and the EF context will retrieve from memory if it is previously attached.
    var attachedEntity = db.Information.FindAsync(personInformation.ID);
    attachedEntity.ExampleValue = personInformation.ExampleValue;
    attachedEntity.ExampleValue2 = personInformation.ExampleValue2;
    ...
    and so on

Upvotes: 2

Related Questions