/// <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);
        }
Esempio n. 2
0
        public override void Act()
        {
            base.Act();

            areEqual = new IdentifiableComparer().Equals(x, y);
        }