2

I'm having some issues in updating and inserting records using ASP.NET MVC and Entity Framework.

I have a form (which is a report) that is dynamically created and can have any amount of questions. I'm trying to allow the user to edit the report and submit the changes so that it is updated in the database.

I am retrieving the report to be edited from the database via a repository then setting it to an instance of ModeratorReport. I'm then changing the value of the properties and using db.SaveChanges to save the changes to the database.

The problem is that it is not saving the changes.

Please could someone advise me on what I am doing wrong?

Here is the Edit Action:

[AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(FormCollection formCollection, int moderatorReportId, string status)
    {
        ModeratorReport reportToEdit = repository.GetModeratorReportById(moderatorReportId);
        List<QuestionAnswer> originalReportAnswers = repository.GetAllModeratorReportAnswers(moderatorReportId, status).ToList();

        foreach (QuestionAnswer answer in originalReportAnswers) {
            reportToEdit.QuestionAnswers.Remove(answer);
        }

        int sectionID;
        int questionID;

        foreach (string key in formCollection.AllKeys)
        {
            var value = formCollection[key.ToString()];

            Match m = Regex.Match(key, "section(\\d+)_question(\\d+)");

            if (m.Success) {
                QuestionAnswer newAnswer = new QuestionAnswer();

                sectionID = Convert.ToInt16(m.Groups[1].Value.ToString());
                questionID = Convert.ToInt16(m.Groups[2].Value.ToString());

                newAnswer.ModeratorReportID = moderatorReportId;
                newAnswer.SectionID = sectionID;
                newAnswer.QuestionID = questionID;
                newAnswer.Answer = value;
                newAnswer.Status = "SAVED";
                reportToEdit.QuestionAnswers.Add(newAnswer);
            }
        }

        reportToEdit.Status = "SAVED";

        AuditItem auditItem = new AuditItem();
        auditItem.ModeratorReportID = moderatorReportId;
        auditItem.Status = "SAVED";
        auditItem.AuditDate = DateTime.Now;
        auditItem.Description = "The Moderator report..."
        auditItem.UserID = User.Identity.Name;
        reportToEdit.Audit.Add(auditItem);

        db.SaveChanges();

        return RedirectToAction("Details", new { id = moderatorReportId });
    }
Gareth Lewis
  • 741
  • 2
  • 15
  • 36

1 Answers1

1

The problem looks like you're just not setting reportToEdit's EntityState to modified. Like so:

reportToEdit.Audit.Add(auditItem); 

reportToEdit.EntityState = EntityState.Modified;
db.SaveChanges();

For more information about the EntityState enumeration, see this MSDN article.

John H
  • 13,157
  • 4
  • 33
  • 68
  • 2
    thanks for you response. I can't seem to use `EntityState` on `reportToEdit`. I tried `db.Entry(reportToEdit).State = EntityState.Modified;` before and I got the error message: `An entity object cannot be referenced by multiple instances of IEntityChangeTracker.` – Gareth Lewis Feb 16 '12 at 14:27
  • That's setting the state correctly then. I'm not completely sure why you're getting the `IEntityChangeTracker` error, but I think it's because the report's `QuestionAnswers` collection is being referenced twice (once by `reportToEdit` and once by `originalReportAnswers`). Unfortunately, I don't know what you can do to solve it in your situation other than sharing the reference to the report from the repository. I hope someone else chimes in because I'd like to know. `IEntityChangeTracker` has bitten me in the past, too. – John H Feb 16 '12 at 14:50
  • Maybe you can do something like this instead. Create a method to remove questions by status in the repository, accepting a reference to the report. Something like: `repository.RemoveAnswersByStatus(reportToEdit, status);` Then: `foreach (QuestionAnswer answer in report.QuestionAnswers) { if (answer.Status == status) report.QuestionAnswers.Remove(answer); }`. – John H Feb 16 '12 at 15:09
  • 1
    I came across the following question: http://stackoverflow.com/questions/5128361/c-sharp-entity-framework-an-entity-object-cannot-be-referenced-by-multiple-inst so I moved the `db.SaveChanges()` into a method in my repository and it seems like it has solved it. I can't verify that though as I have now run into a different problem! – Gareth Lewis Feb 16 '12 at 15:32
  • Ah that makes complete sense. I should've seen that. You should self answer this question when you can. – John H Feb 16 '12 at 15:37