/// <summary> /// Update the given entity in DbContext /// </summary> /// <param name="entity">The entity containing updated property</param> /// <param name="includes">The complex properties that should be included in the Update</param> /// <returns>The entity containing updates</returns> /// <exception cref="System.InvalidOperationException">When the entity doesn't have a keyed property (i.e. an integer Id or a property with the KeyAttribute)</exception> /// <exception cref="System.InvalidOperationException">When the existing entity can't be found by using the key</exception> /// <exception cref="System.InvalidOperationException">If the included collection property of the entity doesn't implement Add or Remove</exception> public virtual T Update(T entity, params string[] includes) { var key = GetKeyValue(entity); var old = Find(key); if (old == null) { throw new InvalidOperationException(string.Format("Entity with key {0} could not be found", key)); } if (includes != null && includes.Length > 0) { RelationshipLoaderAdapter.Load(_dbContext, old, includes); foreach (var property in entity.GetEnumerableProperties() .Where(p => includes.Contains(p.Name))) { var newCollection = property.GetValue(entity, null) as ICollection; var oldCollection = old.GetType() .GetProperty(property.Name) .GetValue(old, null) as ICollection; var add = oldCollection.GetType().GetMethod("Add"); var remove = oldCollection.GetType().GetMethod("Remove"); if (add == null || remove == null) { throw new InvalidOperationException(string.Format("{0} must implement both Add and Remove methods", property.Name)); } var comparer = new IdentifiableComparer(); var newIdentifiables = newCollection.OfType <IIdentifiable>(); var oldIdentifiables = oldCollection.OfType <IIdentifiable>(); var additions = newIdentifiables .Where(item => !oldIdentifiables.Contains(item, comparer)).ToList(); foreach (var newItem in additions) { add.Invoke(oldCollection, new object[] { newItem }); } ; var removals = oldIdentifiables .Where(item => !newIdentifiables.Contains(item, comparer)).ToList(); foreach (var toDelete in removals) { remove.Invoke(oldCollection, new object[] { toDelete }); } ; } } (_dbContext as Context).SetModified(old, entity); return(entity); }
public override void Act() { base.Act(); areEqual = new IdentifiableComparer().Equals(x, y); }