0

I'm trying to do an action with jquery when on button press it changes a value in that database.

My code:

The button:

<a class="fa fa-2x fa-check confirmAnswer" href="#" onclick="Confirm(@item.ID)"></a>

JS:

    var Confirm = function (solutionID) {

    $.ajax({
        type: "POST",
        url: "/Help/ConfirmSolution",
        data: { id: solutionID },
        success: function (response) {
            alert("Survey Deleted");
            location.reload();
        },

    })
}

Controller Action:

    [HttpPost]
    public JsonResult ConfirmSolution(int id)
    {
        HelpSolutionViewModel answer = Mapper.Map<HelpSolution, HelpSolutionViewModel>(unitOfWork.HelpSolutionRepository.GetByID(id));
        answer.Selected = true;
        HelpSolution helpsolution = Mapper.Map<HelpSolutionViewModel, HelpSolution>(answer);
        unitOfWork.HelpSolutionRepository.Update(helpsolution);
        unitOfWork.Save();
        return Json(helpsolution, JsonRequestBehavior.AllowGet);
    }

Repository methods:

        public virtual void Update(TEntity entityToUpdate)
    {
        dbSet.Attach(entityToUpdate);
        context.Entry(entityToUpdate).State = EntityState.Modified;
    }

    public virtual TEntity GetByID(object id)
    {
        return dbSet.Find(id);
    }

The error:

Attaching an entity of type failed because another entity of the same type already has the same primary key valuelockquote

By the way, the other fixes on the similar questions I saw don't help, I tried loads.

3 Answers3

0

By default, Entity Framework tracks all objects that are fetched from the database. So, in your GetById method, you are attaching the object with that id to the entity framework tracker. In your The update method tries to add this object to entity framework again while an object with the same id is already tracked.

A solution for this would be to add AsNoTracking to your GetById method. This will still return the object but entity framework will not track this object.

Jerodev
  • 32,252
  • 11
  • 87
  • 108
  • return dbSet.AsNoTracking.Find(id); gives this error "DbQuery.AsNoTracking()" is a method, which is not valid in the given context –  Feb 01 '18 at 09:34
  • This describes how to use `Find(id)` without tracking: https://stackoverflow.com/a/46223929/743016 – Jerodev Feb 01 '18 at 09:39
  • Thanks, this works, but the method overloads almost most of the project, because I use the regular Find where I don't need detaching. So I created a new method GetByID using that. Thanks for the help! –  Feb 01 '18 at 09:46
0

It looks like you attach an already attached Entry to the dbSet. Try to remove this line:

dbSet.Attach(entityToUpdate);
Jan Henry
  • 33
  • 1
  • 8
0

You don't need this Update method call at all, and all these mapping actions are redundant as well.

You're fetching an object from the database. That object is attached, so you can just modify it and save it.

var helpsolution = unitOfWork.HelpSolutionRepository.GetByID(id);
helpsolution.Selected = true;
unitOfWork.Save();

This emits an UPDATE statement that only updates one field instead of all fields.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291