Search code examples
asp.net-mvcentity-frameworkvalueinjecter

How to update a nested list in Entity Framework?


I cannot find how to update my EstimateLine

public class EstimateLine
{
    [Key]
    [Column(Order = 0)]
    public virtual int EstimateId { get; set; }

    [Key]
    [Column(Order = 1)]
    public virtual int LineId { get; set; }

    public virtual float Price { get; set; }
}

Here is the Estimate class

public class Estimate
{
    public virtual int EstimateId { get; set; }

    public virtual float TotalPrice { get; set; }

    public virtual IList<EstimateLine> Lines { get; set; }
]

Here is the edit

public ActionResult Edit(EstimateViewModel estimateView)
{
        var estimate = db.Estimates.FirstOrDefault(e => e.EstimateId == estimateView.EstimateId);

        if (ModelState.IsValid)
        {
            estimate.InjectFrom(estimateView);

            var lines = new List<EstimateLine>();
            lines.InjectFrom(estimateView.Lines);

            estimate.Lines = lines;

            db.SaveChanges();
            return RedirectToAction("Index");

        }
}

Here it does not delete previous line in DB so I got duplicate key error. How can I tell EF to delete former estimate lines ?


Solution

  • Here is the code I finally created by myself:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(EstimateViewModel estimateView)
        {
            var estimate = db.Estimates.Find(estimateView.EstimateId);
    
    
            if (estimate == null)
                ModelState.AddModelError(String.Empty,"Unknown estimate number");
    
    
            if (ModelState.IsValid)
            {
                // Remove for lines from DB
                estimate.Lines.ToArray().ForEach(line => db.EstimateLines.Remove(line));
    
                // Map user input
                estimate.InjectFrom<DeepCloneInjection>(estimateView);
    
                // Update in db
                try
                {
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
                catch (DbEntityValidationException dbEx)
                {
                    foreach (var error in dbEx.EntityValidationErrors.SelectMany(entityValidationErrors => entityValidationErrors.ValidationErrors))
                    {
                        ModelState.AddModelError(string.Empty, error.ErrorMessage);
                    }
                }
            }
    
            return View("Create", estimateView);
        }