/// <summary>
        /// Method is done as a cleanup, when a resource is deleted, this method will remove the deleted object from an entityInstance reference property
        /// </summary>
        /// <param name="targetResource">Resource to look for in the currentEntityInstance</param>
        /// <param name="property">Reference property to look in on the currentEntityInstance</param>
        /// <param name="currentEntityInstance">currentEntityInstance that may contain the targetResource</param>
        private void SetEntityReferenceToNullOnTargetResourceMatch(ResourceInstance targetResource, ResourceProperty property, ResourceInstance currentEntityInstance)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(property, "property");
            ExceptionUtilities.CheckArgumentNotNull(currentEntityInstance, "currentEntityInstance");
            ExceptionUtilities.Assert(property.Kind == ResourcePropertyKind.ResourceReference, "Should only be called with reference properties");

            string propertyName = property.Name;
            object propertyValue;
            if (currentEntityInstance.TryGetValue(propertyName, out propertyValue) && propertyValue == targetResource)
            {
                this.pendingChanges.Add(() => currentEntityInstance[propertyName] = null);
            }
        }
        private void AddReferenceToCollection_Internal(ResourceInstance targetResource, string propertyName, ResourceInstance resourceToBeAdded, bool addBackReference)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
            ExceptionUtilities.CheckArgumentNotNull(resourceToBeAdded, "resourceToBeAdded");

            var resourceType = this.metadataHelper.ResourceTypes.Single(t => t.FullName == targetResource.ResourceTypeName);
            var property = resourceType.GetAllPropertiesLazily().SingleOrDefault(p => p.Name == propertyName);
            ExceptionUtilities.CheckObjectNotNull(property, "Could not find resource property '{0}' on resource type '{1}'", propertyName, resourceType.FullName);
            ExceptionUtilities.Assert(property.Kind == ResourcePropertyKind.ResourceSetReference, "AddReferenceToCollection called on property '{0}' with kind '{1}'", propertyName, property.Kind);

            object propertyValue;
            if (!targetResource.TryGetValue(propertyName, out propertyValue))
            {
                Type collectionType = this.GetCollectionPropertyType(targetResource.ResourceTypeName, propertyName);
                ExceptionUtilities.CheckObjectNotNull(collectionType, "Could not get collection type for '{0}.{1}'", targetResource.ResourceTypeName, propertyName);
                targetResource[propertyName] = propertyValue = Activator.CreateInstance(collectionType);
            }

            // Check to see if item already exists
            var collection = (IEnumerable)propertyValue;
            foreach (var existingEntity in collection)
            {
                if (this.AreKeysEqual(resourceToBeAdded, (ResourceInstance)existingEntity))
                {
                    // TODO: throw?
                    return;
                }
            }

            var addMethod = collection.GetType().GetMethod("Add");
            ExceptionUtilities.CheckObjectNotNull(addMethod, "Could not find 'Add' method on collection of type: " + collection.GetType());

            addMethod.Invoke(collection, new object[] { resourceToBeAdded });

            if (addBackReference)
            {
                this.SetReverseNavigation(targetResource, resourceToBeAdded, propertyName, false);
            }
        }
        /// <summary>
        /// Method is done as a cleanup, when a resource is deleted, this method will remove the deleted object from an entityInstance collection property
        /// </summary>
        /// <param name="targetResource">Resource to look for in the currentEntityInstance</param>
        /// <param name="property">The collection property to remove from</param>
        /// <param name="currentEntityInstance">currentEntityInstance that may contain the targetResource</param>
        private void RemoveResourceFromCollectionOnTargetResourceMatch(ResourceInstance targetResource, ResourceProperty property, ResourceInstance currentEntityInstance)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(property, "property");
            ExceptionUtilities.CheckArgumentNotNull(currentEntityInstance, "currentEntityInstance");
            ExceptionUtilities.Assert(property.Kind == ResourcePropertyKind.ResourceSetReference, "Should only be called with reference properties");

            string propertyName = property.Name;
            object propertyValue;
            if (!currentEntityInstance.TryGetValue(propertyName, out propertyValue))
            {
                return;
            }

            IEnumerable childCollectionObject = propertyValue as IEnumerable;
            ExceptionUtilities.CheckObjectNotNull(childCollectionObject, "Value of '{0}.{1}' was null or not a collection", currentEntityInstance.ResourceTypeName, propertyName);

            var removeMethod = childCollectionObject.GetType().GetMethod("Remove");
            ExceptionUtilities.CheckObjectNotNull(removeMethod, "Could not find remove method for collection property '{0}.{1}'", currentEntityInstance.ResourceTypeName, propertyName);

            if (childCollectionObject.Cast<object>().Any(o => o == targetResource))
            {
                this.pendingChanges.Add(() => removeMethod.Invoke(childCollectionObject, new object[] { targetResource }));
            }
        }
        private void SetReference_Internal(ResourceInstance targetResource, string propertyName, ResourceInstance propertyValue, bool setBackReference)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");

            var resourceType = this.metadataHelper.ResourceTypes.Single(t => t.FullName == targetResource.ResourceTypeName);
            var property = resourceType.GetAllPropertiesLazily().SingleOrDefault(p => p.Name == propertyName);
            ExceptionUtilities.CheckObjectNotNull(property, "Could not find resource property '{0}' on resource type '{1}'", propertyName, resourceType.FullName);
            ExceptionUtilities.Assert(property.Kind == ResourcePropertyKind.ResourceReference, "SetReference called on property '{0}' with kind '{1}'", propertyName, property.Kind);

            object oldValue;
            if (!targetResource.TryGetValue(propertyName, out oldValue))
            {
                oldValue = null;
            }

            targetResource[propertyName] = propertyValue;
            
            if (setBackReference)
            {
                if (propertyValue == null)
                {
                    propertyValue = (ResourceInstance)oldValue;
                }

                if (propertyValue != null)
                {
                    this.SetReverseNavigation(targetResource, propertyValue, propertyName, (propertyValue == null));
                }
            }
        }