Beispiel #1
0
 internal void HandleAddEntity(object source, string sourceProperty, string sourceEntitySet, ICollection collection, object target, string targetEntitySet)
 {
     if (!this.Context.ApplyingChanges && ((source == null) || !this.IsDetachedOrDeletedFromContext(source)))
     {
         EntityDescriptor entityDescriptor = this.Context.GetEntityDescriptor(target);
         if ((!this.AttachBehavior && ((entityDescriptor == null) || (((source != null) && !this.IsContextTrackingLink(source, sourceProperty, target)) && (entityDescriptor.State != EntityStates.Deleted)))) && (this.CollectionChanged != null))
         {
             EntityCollectionChangedParams arg = new EntityCollectionChangedParams(this.Context, source, sourceProperty, sourceEntitySet, collection, target, targetEntitySet, NotifyCollectionChangedAction.Add);
             if (this.CollectionChanged(arg))
             {
                 return;
             }
         }
         if ((source != null) && this.IsDetachedOrDeletedFromContext(source))
         {
             throw new InvalidOperationException(Strings.DataBinding_BindingOperation_DetachedSource);
         }
         entityDescriptor = this.Context.GetEntityDescriptor(target);
         if (source != null)
         {
             if (!this.AttachBehavior)
             {
                 if (entityDescriptor == null)
                 {
                     this.Context.AddRelatedObject(source, sourceProperty, target);
                 }
                 else if ((entityDescriptor.State != EntityStates.Deleted) && !this.IsContextTrackingLink(source, sourceProperty, target))
                 {
                     this.Context.AddLink(source, sourceProperty, target);
                 }
             }
             else if (entityDescriptor == null)
             {
                 BindingUtils.ValidateEntitySetName(targetEntitySet, target);
                 this.Context.AttachTo(targetEntitySet, target);
                 this.Context.AttachLink(source, sourceProperty, target);
             }
             else if ((entityDescriptor.State != EntityStates.Deleted) && !this.IsContextTrackingLink(source, sourceProperty, target))
             {
                 this.Context.AttachLink(source, sourceProperty, target);
             }
         }
         else if (entityDescriptor == null)
         {
             BindingUtils.ValidateEntitySetName(targetEntitySet, target);
             if (this.AttachBehavior)
             {
                 this.Context.AttachTo(targetEntitySet, target);
             }
             else
             {
                 this.Context.AddObject(targetEntitySet, target);
             }
         }
     }
 }
Beispiel #2
0
 internal void HandleUpdateEntityReference(object source, string sourceProperty, string sourceEntitySet, object target, string targetEntitySet)
 {
     if (!this.Context.ApplyingChanges && !this.IsDetachedOrDeletedFromContext(source))
     {
         EntityDescriptor entityDescriptor = (target != null) ? this.Context.GetEntityDescriptor(target) : null;
         if ((!this.AttachBehavior && ((entityDescriptor == null) || !this.IsContextTrackingLink(source, sourceProperty, target))) && (this.EntityChanged != null))
         {
             EntityChangedParams arg = new EntityChangedParams(this.Context, source, sourceProperty, target, sourceEntitySet, targetEntitySet);
             if (this.EntityChanged(arg))
             {
                 return;
             }
         }
         if (this.IsDetachedOrDeletedFromContext(source))
         {
             throw new InvalidOperationException(Strings.DataBinding_BindingOperation_DetachedSource);
         }
         entityDescriptor = (target != null) ? this.Context.GetEntityDescriptor(target) : null;
         if (target != null)
         {
             if (entityDescriptor == null)
             {
                 BindingUtils.ValidateEntitySetName(targetEntitySet, target);
                 if (this.AttachBehavior)
                 {
                     this.Context.AttachTo(targetEntitySet, target);
                 }
                 else
                 {
                     this.Context.AddObject(targetEntitySet, target);
                 }
                 entityDescriptor = this.Context.GetEntityDescriptor(target);
             }
             if (!this.IsContextTrackingLink(source, sourceProperty, target))
             {
                 if (!this.AttachBehavior)
                 {
                     this.Context.SetLink(source, sourceProperty, target);
                 }
                 else if (entityDescriptor.State != EntityStates.Deleted)
                 {
                     this.Context.AttachLink(source, sourceProperty, target);
                 }
             }
         }
         else
         {
             this.Context.SetLink(source, sourceProperty, null);
         }
     }
 }
Beispiel #3
0
        internal void HandleUpdateEntityReference(
            object source,
            string sourceProperty,
            string sourceEntitySet,
            object target,
            string targetEntitySet)
        {
            if (this.Context.ApplyingChanges)
            {
                return;
            }

            Debug.Assert(source != null, "source can not be null for update operations.");
            Debug.Assert(BindingEntityInfo.IsEntityType(source.GetType()), "source must be an entity with keys.");
            Debug.Assert(!String.IsNullOrEmpty(sourceProperty), "sourceProperty must be a non-empty string for update operations.");
            Debug.Assert(!String.IsNullOrEmpty(sourceEntitySet), "sourceEntitySet must be non-empty string for update operation.");

            if (this.IsDetachedOrDeletedFromContext(source))
            {
                return;
            }

            EntityDescriptor targetDescriptor = target != null?this.Context.GetEntityDescriptor(target) : null;

            bool contextOperationRequired = !this.AttachBehavior &&
                                            (targetDescriptor == null ||
                                             !this.IsContextTrackingLink(source, sourceProperty, target));

            if (contextOperationRequired)
            {
                if (this.EntityChanged != null)
                {
                    EntityChangedParams args = new EntityChangedParams(
                        this.Context,
                        source,
                        sourceProperty,
                        target,
                        sourceEntitySet,
                        targetEntitySet);

                    if (this.EntityChanged(args))
                    {
                        return;
                    }
                }
            }

            if (this.IsDetachedOrDeletedFromContext(source))
            {
                throw new InvalidOperationException(Strings.DataBinding_BindingOperation_DetachedSource);
            }

            targetDescriptor = target != null?this.Context.GetEntityDescriptor(target) : null;

            if (target != null)
            {
                if (targetDescriptor == null)
                {
                    BindingUtils.ValidateEntitySetName(targetEntitySet, target);

                    if (this.AttachBehavior)
                    {
                        this.Context.AttachTo(targetEntitySet, target);
                    }
                    else
                    {
                        this.Context.AddObject(targetEntitySet, target);
                    }

                    targetDescriptor = this.Context.GetEntityDescriptor(target);
                }

                if (!this.IsContextTrackingLink(source, sourceProperty, target))
                {
                    if (this.AttachBehavior)
                    {
                        if (targetDescriptor.State != EntityStates.Deleted)
                        {
                            this.Context.AttachLink(source, sourceProperty, target);
                        }
                    }
                    else
                    {
                        this.Context.SetLink(source, sourceProperty, target);
                    }
                }
            }
            else
            {
                Debug.Assert(!this.AttachBehavior, "During attach operations we must never perform operations for null values.");

                this.Context.SetLink(source, sourceProperty, null);
            }
        }
Beispiel #4
0
        internal void HandleAddEntity(
            object source,
            string sourceProperty,
            string sourceEntitySet,
            ICollection collection,
            object target,
            string targetEntitySet)
        {
            if (this.Context.ApplyingChanges)
            {
                return;
            }

            Debug.Assert(
                (source == null && sourceProperty == null) || (source != null && !String.IsNullOrEmpty(sourceProperty)),
                "source and sourceProperty should either both be present or both be absent.");

            Debug.Assert(target != null, "target must be provided by the caller.");
            Debug.Assert(BindingEntityInfo.IsEntityType(target.GetType()), "target must be an entity type.");

            if (source != null && this.IsDetachedOrDeletedFromContext(source))
            {
                return;
            }

            EntityDescriptor targetDescriptor = this.Context.GetEntityDescriptor(target);

            bool contextOperationRequired = !this.AttachBehavior &&
                                            (targetDescriptor == null ||
                                             (source != null && !this.IsContextTrackingLink(source, sourceProperty, target) && targetDescriptor.State != EntityStates.Deleted));

            if (contextOperationRequired)
            {
                if (this.CollectionChanged != null)
                {
                    EntityCollectionChangedParams args = new EntityCollectionChangedParams(
                        this.Context,
                        source,
                        sourceProperty,
                        sourceEntitySet,
                        collection,
                        target,
                        targetEntitySet,
                        NotifyCollectionChangedAction.Add);

                    if (this.CollectionChanged(args))
                    {
                        return;
                    }
                }
            }

            if (source != null && this.IsDetachedOrDeletedFromContext(source))
            {
                throw new InvalidOperationException(Strings.DataBinding_BindingOperation_DetachedSource);
            }

            targetDescriptor = this.Context.GetEntityDescriptor(target);

            if (source != null)
            {
                if (this.AttachBehavior)
                {
                    if (targetDescriptor == null)
                    {
                        BindingUtils.ValidateEntitySetName(targetEntitySet, target);

                        this.Context.AttachTo(targetEntitySet, target);
                        this.Context.AttachLink(source, sourceProperty, target);
                    }
                    else
                    if (targetDescriptor.State != EntityStates.Deleted && !this.IsContextTrackingLink(source, sourceProperty, target))
                    {
                        this.Context.AttachLink(source, sourceProperty, target);
                    }
                }
                else
                {
                    if (targetDescriptor == null)
                    {
                        this.Context.AddRelatedObject(source, sourceProperty, target);
                    }
                    else
                    if (targetDescriptor.State != EntityStates.Deleted && !this.IsContextTrackingLink(source, sourceProperty, target))
                    {
                        this.Context.AddLink(source, sourceProperty, target);
                    }
                }
            }
            else
            if (targetDescriptor == null)
            {
                BindingUtils.ValidateEntitySetName(targetEntitySet, target);

                if (this.AttachBehavior)
                {
                    this.Context.AttachTo(targetEntitySet, target);
                }
                else
                {
                    this.Context.AddObject(targetEntitySet, target);
                }
            }
        }
Beispiel #5
0
        public bool AddCollection(
            object source,
            string sourceProperty,
            object collection,
            string collectionEntitySet)
        {
            Debug.Assert(collection != null, "'collection' can not be null");
            Debug.Assert(
                BindingEntityInfo.IsDataServiceCollection(collection.GetType()),
                "Argument 'collection' must be an DataServiceCollection<T> of entity type T");

            if (this.graph.ExistsVertex(collection))
            {
                return(false);
            }

            Vertex collectionVertex = this.graph.AddVertex(collection);

            collectionVertex.IsCollection = true;
            collectionVertex.EntitySet    = collectionEntitySet;

            ICollection collectionItf = collection as ICollection;

            if (source != null)
            {
                collectionVertex.Parent         = this.graph.LookupVertex(source);
                collectionVertex.ParentProperty = sourceProperty;
                this.graph.AddEdge(source, collection, sourceProperty);

                Type entityType = BindingUtils.GetCollectionEntityType(collection.GetType());
                Debug.Assert(entityType != null, "Collection must at least be inherited from DataServiceCollection<T>");

                if (!typeof(INotifyPropertyChanged).IsAssignableFrom(entityType))
                {
                    throw new InvalidOperationException(Strings.DataBinding_NotifyPropertyChangedNotImpl(entityType));
                }

                typeof(BindingGraph)
                .GetMethod("SetObserver", BindingFlags.Instance | BindingFlags.NonPublic)
                .MakeGenericMethod(entityType)
                .Invoke(this, new object[] { collectionItf });
            }
            else
            {
                this.graph.Root = collectionVertex;
            }

            Debug.Assert(
                collectionVertex.Parent != null || collectionVertex.IsRootCollection,
                "If parent is null, then collectionVertex should be a root collection");

            this.AttachCollectionNotification(collection);

            foreach (var item in collectionItf)
            {
                this.AddEntity(
                    source,
                    sourceProperty,
                    item,
                    collectionEntitySet,
                    collection);
            }

            return(true);
        }
        /// <summary>Handle changes to navigation properties of a tracked entity. Perform operations on context to reflect the changes.</summary>
        /// <param name="source">The source object that reference the target object through a navigation property.</param>
        /// <param name="sourceProperty">The navigation property in the source object that reference the target object.</param>
        /// <param name="sourceEntitySet">The entity set of the source object.</param>
        /// <param name="target">The target entity.</param>
        /// <param name="targetEntitySet">The entity set name of the target object.</param>
        internal void HandleUpdateEntityReference(
            object source,
            string sourceProperty,
            string sourceEntitySet,
            object target,
            string targetEntitySet)
        {
            if (this.Context.ApplyingChanges)
            {
                return;
            }

            Debug.Assert(source != null, "source can not be null for update operations.");
            Debug.Assert(BindingEntityInfo.IsEntityType(source.GetType()), "source must be an entity with keys.");
            Debug.Assert(!String.IsNullOrEmpty(sourceProperty), "sourceProperty must be a non-empty string for update operations.");
            Debug.Assert(!String.IsNullOrEmpty(sourceEntitySet), "sourceEntitySet must be non-empty string for update operation.");

            // Do not handle update for detached and deleted entities.
            if (this.IsDetachedOrDeletedFromContext(source))
            {
                return;
            }

            // Do we need an operation on context to handle the Update operation.
            EntityDescriptor targetDescriptor = target != null?this.Context.GetEntityDescriptor(target) : null;

            // Following are the conditions where context operation is required:
            // 1. Not a call to Load or constructions i.e. we have Add behavior and not Attach behavior
            // 2. Target entity is not being tracked
            // 3. Target is being tracked but there is no link between the source and target entity
            bool contextOperationRequired = !this.AttachBehavior &&
                                            (targetDescriptor == null ||
                                             !this.IsContextTrackingLink(source, sourceProperty, target));

            if (contextOperationRequired)
            {
                // First give the user code a chance to handle Update link operation.
                if (this.EntityChanged != null)
                {
                    EntityChangedParams args = new EntityChangedParams(
                        this.Context,
                        source,
                        sourceProperty,
                        target,
                        sourceEntitySet,
                        targetEntitySet);

                    if (this.EntityChanged(args))
                    {
                        return;
                    }
                }
            }

            // The user callback code could detach the source.
            if (this.IsDetachedOrDeletedFromContext(source))
            {
                throw new InvalidOperationException(Strings.DataBinding_BindingOperation_DetachedSource);
            }

            // Default implementation.
            targetDescriptor = target != null?this.Context.GetEntityDescriptor(target) : null;

            if (target != null)
            {
                if (targetDescriptor == null)
                {
                    // If the entity set name is not known, then we must throw since we need to know the
                    // entity set in order to add/attach the referenced object to it's entity set.
                    BindingUtils.ValidateEntitySetName(targetEntitySet, target);

                    if (this.AttachBehavior)
                    {
                        this.Context.AttachTo(targetEntitySet, target);
                    }
                    else
                    {
                        this.Context.AddObject(targetEntitySet, target);
                    }

                    targetDescriptor = this.Context.GetEntityDescriptor(target);
                }

                // if the entity is already tracked, then just set/attach the link. However, do
                // not try to attach the link if the target is in Deleted state.
                if (!this.IsContextTrackingLink(source, sourceProperty, target))
                {
                    if (this.AttachBehavior)
                    {
                        if (targetDescriptor.State != EntityStates.Deleted)
                        {
                            this.Context.AttachLink(source, sourceProperty, target);
                        }
                    }
                    else
                    {
                        this.Context.SetLink(source, sourceProperty, target);
                    }
                }
            }
            else
            {
                Debug.Assert(!this.AttachBehavior, "During attach operations we must never perform operations for null values.");

                // The target could be null in which case we just need to set the link to null.
                this.Context.SetLink(source, sourceProperty, null);
            }
        }
        /// <summary>Handle Adds to a tracked DataServiceCollection. Perform operations on context to reflect the changes.</summary>
        /// <param name="source">The source object that reference the target object through a navigation property.</param>
        /// <param name="sourceProperty">The navigation property in the source object that reference the target object.</param>
        /// <param name="sourceEntitySet">The entity set of the source object.</param>
        /// <param name="collection">The collection containing the target object.</param>
        /// <param name="target">The target entity to attach.</param>
        /// <param name="targetEntitySet">The entity set name of the target object.</param>
        internal void HandleAddEntity(
            object source,
            string sourceProperty,
            string sourceEntitySet,
            ICollection collection,
            object target,
            string targetEntitySet)
        {
            if (this.Context.ApplyingChanges)
            {
                return;
            }

            Debug.Assert(
                (source == null && sourceProperty == null) || (source != null && !String.IsNullOrEmpty(sourceProperty)),
                "source and sourceProperty should either both be present or both be absent.");

            Debug.Assert(target != null, "target must be provided by the caller.");
            Debug.Assert(BindingEntityInfo.IsEntityType(target.GetType()), "target must be an entity type.");

            // Do not handle add for already detached and deleted entities.
            if (source != null && this.IsDetachedOrDeletedFromContext(source))
            {
                return;
            }

            // Do we need an operation on context to handle the Add operation.
            EntityDescriptor targetDescriptor = this.Context.GetEntityDescriptor(target);

            // Following are the conditions where context operation is required:
            // 1. Not a call to Load or constructions i.e. we have Add behavior and not Attach behavior
            // 2. Target entity is not being tracked
            // 3. Target is being tracked but there is no link between the source and target entity and target is in non-deleted state
            bool contextOperationRequired = !this.AttachBehavior &&
                                            (targetDescriptor == null ||
                                             (source != null && !this.IsContextTrackingLink(source, sourceProperty, target) && targetDescriptor.State != EntityStates.Deleted));

            if (contextOperationRequired)
            {
                // First give the user code a chance to handle Add operation.
                if (this.CollectionChanged != null)
                {
                    EntityCollectionChangedParams args = new EntityCollectionChangedParams(
                        this.Context,
                        source,
                        sourceProperty,
                        sourceEntitySet,
                        collection,
                        target,
                        targetEntitySet,
                        NotifyCollectionChangedAction.Add);

                    if (this.CollectionChanged(args))
                    {
                        return;
                    }
                }
            }

            // The user callback code could detach the source.
            if (source != null && this.IsDetachedOrDeletedFromContext(source))
            {
                throw new InvalidOperationException(Strings.DataBinding_BindingOperation_DetachedSource);
            }

            // Default implementation.
            targetDescriptor = this.Context.GetEntityDescriptor(target);

            if (source != null)
            {
                if (this.AttachBehavior)
                {
                    // If the target entity is not being currently tracked, we attach both the
                    // entity and the link between source and target entity.
                    if (targetDescriptor == null)
                    {
                        BindingUtils.ValidateEntitySetName(targetEntitySet, target);

                        this.Context.AttachTo(targetEntitySet, target);
                        this.Context.AttachLink(source, sourceProperty, target);
                    }
                    else
                    if (targetDescriptor.State != EntityStates.Deleted && !this.IsContextTrackingLink(source, sourceProperty, target))
                    {
                        // If the target is already being tracked, then we attach the link if it
                        // does not already exist between the source and target entities and the
                        // target entity is not already in Deleted state.
                        this.Context.AttachLink(source, sourceProperty, target);
                    }
                }
                else
                {
                    // The target will be added and link from source to target will get established in the code
                    // below. Note that if there is already target present then we just try to establish the link
                    // however, if the link is also already established then we don't do anything.
                    if (targetDescriptor == null)
                    {
                        // If the entity is not tracked, that means the entity needs to
                        // be added to the context. We need to call AddRelatedObject,
                        // which adds via the parent (for e.g. POST Customers(0)/Orders).
                        this.Context.AddRelatedObject(source, sourceProperty, target);
                    }
                    else
                    if (targetDescriptor.State != EntityStates.Deleted && !this.IsContextTrackingLink(source, sourceProperty, target))
                    {
                        // If the entity is already tracked, then we just add the link.
                        // However, we would not do it if the target entity is already
                        // in a Deleted state.
                        this.Context.AddLink(source, sourceProperty, target);
                    }
                }
            }
            else
            if (targetDescriptor == null)
            {
                // The source is null when the DataServiceCollection is the root collection.
                BindingUtils.ValidateEntitySetName(targetEntitySet, target);

                if (this.AttachBehavior)
                {
                    // Attach the target entity.
                    this.Context.AttachTo(targetEntitySet, target);
                }
                else
                {
                    // Add the target entity.
                    this.Context.AddObject(targetEntitySet, target);
                }
            }
        }