I decided to solve the problem with GraphDiff, Complete solution below. I'm open to someone posting a more elegant solution.
public Boolean SubmitProfiles(String dcmClientId, List<DcmProfile> dcmProfiles)
{
try
{
using (var dc = new JCEContext())
{
var existing = dc.DcmProfiles.AsNoTracking().Where(x => x.DcmClientId == dcmClientId).ToList();
var added = dcmProfiles.Except(existing, x => x.Id).ToList();
var deleted = existing.Except(dcmProfiles, x => x.Id).ToList();
var modified = dcmProfiles.Except(added, x => x.Id);
// Update modified profiles
foreach (var dcmProfile in modified)
dc.UpdateGraph(dcmProfile, map => map
.OwnedCollection(profile => profile.Plugins, with => with
.OwnedCollection(plugin => plugin.Counters)));
// Add new profiles
added.ForEach(profile => dc.Entry(profile).State = EntityState.Added);
// Delete nonexistent profiles
deleted.ForEach(profile => dc.Entry(profile).State = EntityState.Deleted);
dc.SaveChanges();
}
return true;
}
catch (Exception ex)
{
Log.ErrorException(ex.Message, ex);
return false;
}
}
The below is an extension method that compare values from two lists and return entities from one which are not present in the other.
public static IEnumerable<T> Except<T, TKey>(this IEnumerable<T> items, IEnumerable<T> other, Func<T, TKey> getKey)
{
return from item in items
join otherItem in other on getKey(item)
equals getKey(otherItem) into tempItems
from temp in tempItems.DefaultIfEmpty()
where ReferenceEquals(null, temp) || temp.Equals(default(T))
select item;
}