I was messing with something like this ...
protected void UpdateChildCollection<Tparent, Tid , Tchild>(Tparent dbItem, Tparent newItem, Func<Tparent, IEnumerable<Tchild>> selector, Func<Tchild, Tid> idSelector) where Tchild : class { var dbItems = selector(dbItem).ToList(); var newItems = selector(newItem).ToList(); if (dbItems == null && newItems == null) return; var original = dbItems?.ToDictionary(idSelector) ?? new Dictionary<Tid, Tchild>(); var updated = newItems?.ToDictionary(idSelector) ?? new Dictionary<Tid, Tchild>(); var toRemove = original.Where(i => !updated.ContainsKey(i.Key)).ToArray(); var removed = toRemove.Select(i => DbContext.Entry(i.Value).State = EntityState.Deleted).ToArray(); var toUpdate = original.Where(i => updated.ContainsKey(i.Key)).ToList(); toUpdate.ForEach(i => DbContext.Entry(i.Value).CurrentValues.SetValues(updated[i.Key])); var toAdd = updated.Where(i => !original.ContainsKey(i.Key)).ToList(); toAdd.ForEach(i => DbContext.Set<Tchild>().Add(i.Value)); }
which you can call with:
UpdateChildCollection(dbCopy, detached, p => p.MyCollectionProp, collectionItem => collectionItem.Id)
Unfortunately, this view drops if there are collection properties for the child type that also need to be updated. Given an attempt to solve this problem, passing an IRepository (with basic CRUD methods), which will be responsible for calling UpdateChildCollection on its own. Repo call instead of direct calls in DbContext.Entry.
I don’t know how all this will be carried out on a scale, but I’m not sure what else to do with this problem.
brettman Nov 23 '15 at 18:54 2015-11-23 18:54
source share