AliAzra
AliAzra

Reputation: 919

Entity Framework: Can't save data because of tracking

I have got a complex class. Feedback and Steps. I am using SQL database and .NET Core 2. I can save main properties but can't save the sub class FeedbackSteps properties

public class FeedbackModel
{
    [Key]
    public int FeedBackID { get; set; }
    public DateTime FBDate { get; set; }
    public bool? VideoStatus { get; set; }
    public string VideoDetail { get; set; }
    public string PITFeedBack { get; set; }
    public int ActivityID { get; set; }
    public virtual ActivityModel Activity { get; set; }
    public int ClientID { get; set; }
    public virtual ClientModel Client { get; set; }
    public int? SupportPlanID { get; set; }
    public virtual SupportPlanModel SupportPlan { get; set; }
    public int EmployeeID { get; set; }
    public virtual Employee Employee { get; set; }
    public bool FeedbackStatus { get; set; } = true;

    virtual public List<FeedbackStepModel> FeedbackSteps { get; set; }
}

public class FeedbackStepModel
{
    [Key]
    public int FeedbackStepID { get; set; }
    public int FeedbackID { get; set; } = 0;
    public int SupportPlanID { get; set; }    
    public int StepNumber { get; set; }
    public string StepDetail { get; set; }
    public string AchievementStatus { get; set; }
    public string AchievementComment { get; set; }
}

This is the post method. View returns Edited or Updated feedback and i just want to update the database with new data

    [HttpPost]
    public IActionResult Edit(FeedbackModel feedback)
    {
        if (ModelState.IsValid)
        {
            feedbackRepository.Save(feedback);
            TempData["message"] = $"Feedback has been saved";
            return RedirectToAction("Index");
        }
    }

After EDIT, I would like to save it...

    public void Save(FeedbackModel feedback)
    {
        if (feedback.FeedBackID == 0)
        {
            context.FeedbackModels.Add(feedback);
        }
        else
        {
            FeedbackModel dbEntry = context.FeedbackModels.Include(s => s.FeedbackSteps).FirstOrDefault(a => a.FeedBackID == feedback.FeedBackID);

            if (dbEntry != null)
            {
                dbEntry.FeedBackID = feedback.FeedBackID;
                dbEntry.FBDate = feedback.FBDate;
                dbEntry.VideoStatus = feedback.VideoStatus;
                dbEntry.VideoDetail = feedback.VideoDetail;
                dbEntry.SupportPlanID = feedback.SupportPlanID;
                dbEntry.ActivityID = feedback.ActivityID;
                dbEntry.PITFeedBack = feedback.PITFeedBack;
                dbEntry.ClientID = feedback.ClientID;
                dbEntry.EmployeeID = feedback.EmployeeID;                   
                dbEntry.FeedbackStatus = feedback.FeedbackStatus;
                dbEntry.FeedbackSteps = feedback.FeedbackSteps;
            }
        }

        context.SaveChanges();
    }

But I get this error all the time

The instance of entity type 'FeedbackStepModel' cannot be tracked because another instance with the key value '{FeedbackStepID: 1}' is already being tracked.

When attaching existing entities, ensure that only one entity instance with a given key value is attached.

Upvotes: 1

Views: 511

Answers (1)

TanvirArjel
TanvirArjel

Reputation: 32059

Your FeedbackModel update operation with children (FeedbackSteps) should be as follows:

FeedbackModel dbEntry = context.FeedbackModels.Include(s => s.FeedbackSteps).FirstOrDefault(a => a.FeedBackID == feedback.FeedBackID);

if (dbEntry != null)
{
      dbEntry.FeedBackID = feedback.FeedBackID;
      dbEntry.FBDate = feedback.FBDate;
      dbEntry.VideoStatus = feedback.VideoStatus;
      dbEntry.VideoDetail = feedback.VideoDetail;
      dbEntry.SupportPlanID = feedback.SupportPlanID;
      dbEntry.ActivityID = feedback.ActivityID;
      dbEntry.PITFeedBack = feedback.PITFeedBack;
      dbEntry.ClientID = feedback.ClientID;
      dbEntry.EmployeeID = feedback.EmployeeID;                   
      dbEntry.FeedbackStatus = feedback.FeedbackStatus;

      dbEntry.FeedbackSteps.Clear(); // First you have to clear the existing feedBackSteps

      foreach(FeedbackStep feedBackStep in feedback.FeedbackSteps)
      {
         dbEntry.FeedbackSteps.Add(feedBackStep); // You have to add new and updated feedBackStep here.
      }
}

If dbEntry.FeedbackSteps.Clear(); does not work (may be in EF Core 2.0 or lower Clear() does not work) then replace dbEntry.FeedbackSteps.Clear(); with the following code:

foreach(FeedbackStep feedbackStepToBeRemoved in dbEntry.FeedbackSteps)
{
   context.Remove(feedbackStepToBeRemoved);
}

Upvotes: 1

Related Questions