Tuesday 24 May 2016

c# - 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 FeedbackSteps { get; set; }

}


and



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 AchivmentStatus { get; set; }
public string AchivmentComment { 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 it gives me this error all the time



Message=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.

Answer




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

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...