There has to be a better way to handle child Saving/Updating in EF 6. Surely this duplication is just a failure on my part.
Entity
public partial class MyParentType
{
    public MyParentType()
    {
        this.children = new HashSet<child>();
    }
    public int parentID { get; set; }
    public virtual ICollection<child> children { get; set; }
}
Add/Update
public class MyRepository : IMyRepository
{
    private readonly IErrorLogger _logger;
    private readonly CorporateEntities _context;
    public MyRepository(IErrorLogger logger)
    {
        _logger = logger;
        _context = new CorporateEntities();
    }
    public void Update(IEnumerable<MyParentType> parents)
    {
        try
        {
            Add(parents.Where(x => x.parentID == 0));
            var updatedData = parents.Where(x => x.parentID != 0);
            foreach (var parent in updatedData)
            {
                var original = _context.MyParentTypes.FirstOrDefault(x => x.parentID == parent.parentID);
                _context.Entry(original).CurrentValues.SetValues(parent);
                UpdateChildren(parent);
            }
            _context.SaveChanges();
        }
        catch (Exception exception)
        {
            _logger.Error(exception.Message, exception);
        }
    }
    public void Add(IEnumerable<MyParentType> parents)
    {
        if (parents == null)
            return;
        try
        {
            _context.MyParentTypes.AddRange(parents);
            _context.SaveChanges();
        }
        catch (Exception exception)
        {
            _logger.Error(exception.Message, exception);
        }
    }
    private void UpdateChildren(MyParentType parent)
    {
        try
        {
            AddChildren(parent.children.Where(x => x.childID == 0));
            var updatedData = parent.children.Where(x => x.childID != 0);
            foreach (var child in updatedData)
            {
                var original = _context.children.FirstOrDefault(x => x.childID == child.childID);
                _context.Entry(original).CurrentValues.SetValues(child);
            }
            _context.SaveChanges();
        }
        catch (Exception exception)
        {
            _logger.Error(exception.Message, exception);
        }
    }
    private void AddChildren(IEnumerable<child> references)
    {
        try
        {
            _context.children.AddRange(references);
            _context.SaveChanges();
        }
        catch (Exception exception)
        {
            _logger.Error(exception.Message, exception);
            throw;
        }
    }
}
I feel like I shouldn't have to duplicate this or write a generic method to handle both cases. Did I miss something in the EF docuemtation where I can update a child entity with the parent one?
I recommend you use GraphDiff. With this library your Update method would be as I show below:
 public void Update(IEnumerable<MyParentType> parents)
 {
   try
   {
       Add(parents.Where(x => x.parentID == 0));
       var updatedData = parents.Where(x => x.parentID != 0);
       foreach (var parent in updatedData)
       {
          _context.UpdateGraph(parent, map => map.OwnedCollection(p => p.children));   
       }
       _context.SaveChanges();
   }
   catch (Exception exception)
   {
     _logger.Error(exception.Message, exception);
   }
}
This way you don't need to worry about manage the children's states.
If you don't want to use GraphDiff, then you need to manage the state of the children manually:
 public void Update(IEnumerable<MyParentType> parents)
 {
   try
   {
       foreach (var parent in parents)
       {
         if(parent.Id==0)
         {
          _context.MyParentTypes.Add(parent);
         }
         else
         { 
            //When you change the state to Modified all the scalar properties of the entity will be marked as modified
           _context.Entry(parent).State = EntityState.Modified;
            foreach(var child in parent.children)
            {
               context.Entry(child).State =child.Id>0? EntityState.Modified:EntityState.Added;  
            }
         }
       }
       _context.SaveChanges();
   }
   catch (Exception exception)
   {
     _logger.Error(exception.Message, exception);
   }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With