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 });
    }

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

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.
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.
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); }.
I came across the following question: stackoverflow.com/questions/5128361/… 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!
Ah that makes complete sense. I should've seen that. You should self answer this question when you can.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.