private void RevertCollectionChange <T>(IEnumerable entities)
            where T : class, IDbEntity
        {
            ICollection <T> collection = entities as ICollection <T>;

            if (Before == null && After != null && DbEntityUtilities.IsIDbEntity(After.GetType()))
            {
                // This property change refers to a newly added entity to this collection. To revert it, remove the added entity from the collection
                collection.Remove(After as T);
            }
            else if (Before != null && DbEntityUtilities.IsIDbEntity(Before.GetType()) && After == null && !collection.Contains(Before as T))
            {
                // This property change refers to an entity removed from this collection. To revert it, re-add the removed entity to the collection
                collection.Add(Before as T);
            }
        }
        private void ApplyCollectionChange <T>(IEnumerable entities)
            where T : class, IDbEntity
        {
            // If remove (i.e. before = typeof(IDbEntity), after = null), remove before value
            ICollection <T> collection = entities as ICollection <T>;

            if (Before == null && After != null && DbEntityUtilities.IsIDbEntity(After.GetType()) && !collection.Contains(After as T))
            {
                // This property change refers to a newly added entity to this collection. To re-apply it, re-add the added entity to the collection
                collection.Add(After as T);
            }
            else if (Before != null && DbEntityUtilities.IsIDbEntity(Before.GetType()) && After == null)
            {
                // This property change refers to an entity removed from this collection. To re-apply it, remove the removed entity from the collection
                collection.Remove(Before as T);
            }
        }
        private void EntityPropertyChanged(object sender, DbEntityPropertyChangedEventArgs e, string path)
        {
            IDbEntity      entity = sender as IDbEntity;
            PropertyChange change = null;

            // Save a reference to the property changed
            if (!_isCreatingHandlers && IsValid(sender.GetType(), path, e.PropertyName) && (!e.PropertyName.Equals("IsDeleted") || entity.State == EntityState.Persisted))
            {
                string       propertyPath         = path + e.PropertyName;
                PropertyInfo p                    = entity.GetType().GetProperty(e.PropertyName);
                bool         isEnumerable         = p.GetGetMethod().ReturnType.IsIEnumerable();
                bool         isDbEntityEnumerable = false;
                bool         isIDbEntity          = DbEntityUtilities.IsIDbEntity(p);
                if (isIDbEntity)
                {
                    propertyPath = propertyPath + ".";
                    if (e.Before != null)
                    {
                        RemoveHandlers(e.Before as IDbEntity, propertyPath);
                    }

                    if (e.After != null)
                    {
                        // Defer any changes tracking that might have been recorded on the navigation entity to the root entity
                        IDbEntity navigationEntity = e.After as IDbEntity;
                        if (_entity.IsTrackingChanges)
                        {
                            MergeChanges(navigationEntity, propertyPath, !_entity.IsTrackingChanges);
                        }
                        CreateHandlers(navigationEntity, propertyPath);
                    }
                }
                else if ((isEnumerable && p.GetGetMethod().ReturnType.GetGenericArguments().Count() > 0 && DbEntityUtilities.IsIDbEntity(p.GetGetMethod().ReturnType.GetGenericArguments()[0])))
                {
                    isDbEntityEnumerable = true;
                    if (e.Before != null)
                    {
                        RemoveCollectionHandlers(entity, e.Before as IEnumerable <IDbEntity>, path, propertyPath + ".", p);
                    }

                    if (e.After != null)
                    {
                        foreach (IDbEntity navigationEntity in e.After as IEnumerable <IDbEntity> )
                        {
                            if (navigationEntity != null)
                            {
                                string entityPath = DbEntityUtilities.GenerateCollectionItemPath(propertyPath, navigationEntity.Guid);
                                if (_entity.IsTrackingChanges)
                                {
                                    MergeChanges(navigationEntity, entityPath, !_entity.IsTrackingChanges);
                                }
                                CreateHandlers(navigationEntity, entityPath);
                            }
                        }
                    }
                }

                if (_entity.IsTrackingChanges)
                {
                    change = new PropertyChange(path, e.PropertyName, entity.Guid, e.Before, e.After, entity.State);
                    if (isDbEntityEnumerable)
                    {
                        change = new PropertyChange(path, e.PropertyName, entity.Guid, e.Before, e.After);
                    }

                    PurgeLast(p.GetGetMethod().ReturnType, change);
                    AddChange(change);
                    Validate(change, isIDbEntity);
                }

                //_logTo.DebugQueue(new EntityPropertyChangedLogEntry(SettingsModel.Current.User.id, entity.PrimaryKeys, entity.GetType(), propertyPath));
            }
        }