Exemplo n.º 1
0
        /// <summary>
        /// Create a 4 level compositional hierarchy that includes both
        /// collection and singleton compositions
        /// </summary>
        public static List <Parent> CreateCompositionHierarchy()
        {
            int parentKey          = 1;
            int childKey           = 1;
            int grandChildKey      = 1;
            int greatGrandChildKey = 1;

            List <Parent> parents = new List <Parent>();

            for (int i = 0; i < 3; i++)
            {
                Parent p = new Parent
                {
                    ID = parentKey++
                };
                parents.Add(p);
                for (int j = 0; j < 3; j++)
                {
                    Child c = new Child
                    {
                        ID = childKey++, ParentID = p.ID, Parent = p
                    };
                    p.Children.Add(c);
                    for (int k = 0; k < 3; k++)
                    {
                        GrandChild gc = new GrandChild
                        {
                            ID = grandChildKey++, ParentID = c.ID, Parent = c
                        };
                        c.Children.Add(gc);

                        // add singleton child to grand child
                        gc.Child = new GreatGrandChild
                        {
                            ID = greatGrandChildKey++, ParentID = gc.ID, Parent = gc
                        };
                    }
                }
            }

            return(parents);
        }
 public void CustomOp_GrandChild(GrandChild grandChild)
 {
     ((CompositionEntityBase)grandChild).OperationResult += ",CustomOp_GrandChild";
 }
 public void CustomOp_GrandChild(GrandChild grandChild)
 {
     this.SetOperationInvoked(grandChild, "CustomOp_GrandChild");
     ((CompositionEntityBase)grandChild).OperationResult += ",CustomOp_GrandChild";
 }
 /// <summary>
 /// Invokes the 'CustomOp_GrandChild' method of the specified <see cref="GrandChild"/> entity.
 /// </summary>
 /// <param name="grandChild">The <see cref="GrandChild"/> entity instance.</param>
 public void CustomOp_GrandChild(GrandChild grandChild)
 {
     grandChild.CustomOp_GrandChild();
 }
        public void HierarchicalChangeTracking_ChildAssociationUpdates_EntityCollection()
        {
            CompositionScenarios_Explicit ctxt = new CompositionScenarios_Explicit(CompositionScenarios_Explicit_Uri);
            Parent parent = CreateCompositionHierarchy(3, 3);
            ctxt.Parents.Attach(parent);

            // Remove a child and add one
            Child c = parent.Children.First();
            GrandChild gc = c.Children.ToArray()[1];
            GreatGrandChild ggc = gc.Child;
            gc.Child = null;   // remove
            GrandChild newGc = new GrandChild
            {
                ID = 100
            };
            GreatGrandChild newGgc = new GreatGrandChild
            {
                ID = 100
            };
            c.Children.Add(newGc);   // add
            newGc.Child = newGgc; 
            Assert.IsTrue(parent.HasChanges);
            Assert.IsTrue(c.HasChanges);
            Assert.IsTrue(gc.HasChanges);
            Assert.IsFalse(ggc.HasChanges);
            Assert.AreEqual(EntityState.Deleted, ggc.EntityState);
            EntityChangeSet cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.AddedEntities.Count == 2 && cs.ModifiedEntities.Count == 3 && cs.RemovedEntities.Count == 1);

            // Reject the remove and verify state
            ((IRevertibleChangeTracking)gc).RejectChanges();
            Assert.IsTrue(parent.HasChanges);
            Assert.IsTrue(c.HasChanges);
            Assert.IsFalse(gc.HasChanges);
            Assert.IsFalse(ggc.HasChanges);
            cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.AddedEntities.Count == 2 && cs.ModifiedEntities.Count == 2 && cs.RemovedEntities.Count == 0);
            Assert.AreSame(ggc, gc.Child);

            ((IRevertibleChangeTracking)c).RejectChanges();
            cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.AddedEntities.Count == 0 && cs.ModifiedEntities.Count == 0 && cs.RemovedEntities.Count == 0);
        }
Exemplo n.º 6
0
        public void InsertGrandChild(GrandChild grandChild)
        {
            SetOperationInvoked(grandChild);

            ((CompositionEntityBase)grandChild).OperationResult = "Insert";
        }
Exemplo n.º 7
0
 public void CustomOp_GrandChild(GrandChild grandChild)
 {
     ((CompositionEntityBase)grandChild).OperationResult += ",CustomOp_GrandChild";
 }
        public void UpdateGrandChild(GrandChild grandChild)
        {
            SetOperationInvoked(grandChild);

            ((CompositionEntityBase)grandChild).OperationResult = "Update";
        }
        [WorkItem(188918)]  // CSDMain
        public void HierarchicalChangeTracking_RejectChanges_MultipleChildChanges()
        {
            CompositionScenarios_Explicit ctxt = new CompositionScenarios_Explicit(CompositionScenarios_Explicit_Uri);
            Parent parent = CreateCompositionHierarchy(3, 3);
            ctxt.Parents.Attach(parent);

            // update the child first
            Child child = parent.Children.First();
            child.OperationResult = "complete";
            // update the grandchild
            child.Children.First().OperationResult = "complete";
            // add a new grandchild
            GrandChild newGrandChild = new GrandChild { ID = 25 };
            child.Children.Add(newGrandChild);

            // Reject changes should revert child before either grandchild (alpha order). We need
            // to make sure this works with multiple grandchildren.
            ctxt.RejectChanges();

            EntityChangeSet cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.IsEmpty, "cs.IsEmpty is false");
            Assert.AreEqual(EntityState.Unmodified, child.EntityState, "EntityState.Unmodified != child.EntityState");
        }
        /// <summary>
        /// Make a bunch of multilevel updates to a hierarchy
        /// </summary>
        private void HierarchyUpdate(Uri testUri)
        {
            CompositionScenarios_Explicit ctxt = new CompositionScenarios_Explicit(testUri);

            Parent parent = null;
            SubmitOperation so = null;
            LoadOperation lo = ctxt.Load(ctxt.GetParentsQuery(), false);
            IEnumerable<Entity> expectedUpdates = null;

            EnqueueConditional(() => lo.IsComplete);
            EnqueueCallback(delegate
            {
                TestHelperMethods.AssertOperationSuccess(lo);

                parent = ctxt.Parents.First();
                Child existingChild = parent.Children.First();
                Assert.AreSame(parent, ((Entity)existingChild).Parent);
                GrandChild existingGrandChild = existingChild.Children.Skip(1).Take(1).Single();

                // add a few new children
                Child newChild = new Child
                {
                    ID = 100
                };
                parent.Children.Add(newChild);
                GrandChild newGc = new GrandChild
                {
                    ID = 100
                };
                existingChild.Children.Add(newGc);
                GreatGrandChild newGgc = new GreatGrandChild
                {
                    ID = 100
                };

                // update a few children
                GrandChild updatedGrandChild = existingChild.Children.First(p => p.EntityState != EntityState.New);
                updatedGrandChild.Property += "x";

                // remove a few children
                GreatGrandChild deletedGreatGrandChild = existingGrandChild.Child;
                existingGrandChild.Child = null;

                // invoke a custom method on the parent
                parent.CustomOp_Parent();

                EntityChangeSet cs = ctxt.EntityContainer.GetChanges();
                Assert.IsTrue(cs.AddedEntities.Count == 2 && cs.ModifiedEntities.Count == 4 && cs.RemovedEntities.Count == 1);
                Assert.IsTrue(cs.AddedEntities.Contains(newChild));
                Assert.IsTrue(cs.AddedEntities.Contains(newGc));
                Assert.IsTrue(cs.ModifiedEntities.Contains(parent));
                Assert.IsTrue(cs.ModifiedEntities.Contains(existingChild));
                Assert.IsTrue(cs.ModifiedEntities.Contains(existingGrandChild));
                Assert.IsTrue(cs.ModifiedEntities.Contains(updatedGrandChild));
                Assert.IsTrue(cs.RemovedEntities.Contains(deletedGreatGrandChild));

                // direct test verifying that we create the correct set of
                // ChangeSetEntries to send to the server
                int modifiedCount = cs.AddedEntities.Count + cs.ModifiedEntities.Count + cs.RemovedEntities.Count;
                int expectedOperationCount = 24;
                IEnumerable<ChangeSetEntry> entityOps = ChangeSetBuilder.Build(cs);
                int entityOpCount = entityOps.Count();
                Assert.AreEqual(expectedOperationCount, entityOpCount);
                Assert.AreEqual(expectedOperationCount - modifiedCount, entityOps.Count(p => p.Operation == EntityOperationType.None));

                // verify that original associations are set up correctly
                this.ValidateEntityOperationAssociations(entityOps);

                expectedUpdates = cs.Where(p => p.HasChildChanges || p.HasPropertyChanges).ToArray();
                so = ctxt.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
            });
            EnqueueConditional(() => so.IsComplete);
            EnqueueCallback(delegate
            {
                this.VerifySuccess(ctxt, so, expectedUpdates);

                // verify that the custom method was invoked
                string[] updateResults = parent.OperationResult.Split(',');
                Assert.IsTrue(updateResults.Contains("CustomOp_Parent"));
            });

            EnqueueTestComplete();
        }
        public void Composition_InvalidParentUpdate_EntityRef()
        {
            ConfigurableEntityContainer container = new ConfigurableEntityContainer();
            container.CreateSet<GrandChild>(EntitySetOperations.All);
            container.CreateSet<GreatGrandChild>(EntitySetOperations.All);
            EntitySet<GrandChild> parentSet = container.GetEntitySet<GrandChild>();
            EntitySet<GreatGrandChild> childSet = container.GetEntitySet<GreatGrandChild>();

            GrandChild parent1 = new GrandChild() { ID = 1 };
            GrandChild parent2 = new GrandChild() { ID = 2 };
            GreatGrandChild child = new GreatGrandChild() { ID = 1, Parent = parent1 };

            parentSet.Attach(parent1);
            parentSet.Attach(parent2);

            Assert.IsTrue(childSet.IsAttached(child), "Child was not attached automatically.");
            Assert.AreSame(parent1, ((Entity)child).Parent, "Entity.Parent doesn't reflect the parent-child relationship.");

            // point the child to a new parent, which results
            // in the child being reparented (an invalid update)
            child.Parent = parent2;

            EntityChangeSet changeSet = container.GetChanges();
            Assert.AreEqual(EntityState.Modified, child.EntityState);
            Assert.AreEqual(EntityState.Modified, parent1.EntityState);
            Assert.AreEqual(EntityState.Modified, parent2.EntityState);

            // Verify that changing the parent throws an exception when
            // changes are validated
            ExceptionHelper.ExpectInvalidOperationException(delegate
            {
                ChangeSetBuilder.CheckForInvalidUpdates(changeSet);
            }, string.Format(Resource.Entity_CantReparentComposedChild, child));
        }
        public void Composition_MultipleRemoveReadds()
        {
            ConfigurableEntityContainer container = new ConfigurableEntityContainer();
            container.CreateSet<Parent>(EntitySetOperations.All);
            container.CreateSet<Child>(EntitySetOperations.All);
            container.CreateSet<GrandChild>(EntitySetOperations.All);
            container.CreateSet<GreatGrandChild>(EntitySetOperations.All);
            EntitySet<Parent> parentSet = container.GetEntitySet<Parent>();
            EntitySet<Child> childSet = container.GetEntitySet<Child>();
            EntitySet<GreatGrandChild> ggChildSet = container.GetEntitySet<GreatGrandChild>();

            Parent parent = new Parent() { ID = 1 };
            Child child = new Child() { ID = 1, Parent = parent };
            container.LoadEntities(new Entity[] { parent, child });

            parent.Children.Remove(child);
            Assert.AreEqual(EntityState.Deleted, child.EntityState);
            Assert.IsFalse(childSet.Contains(child));

            parent.Children.Add(child);
            Assert.AreEqual(EntityState.Modified, child.EntityState);
            Assert.IsTrue(childSet.Contains(child));

            parent.Children.Remove(child);
            Assert.AreEqual(EntityState.Deleted, child.EntityState);
            Assert.IsFalse(childSet.Contains(child));

            // verify the same scenario for a singleton composition
            GrandChild gc = new GrandChild { ID = 1 };
            GreatGrandChild ggc = new GreatGrandChild { ID = 1, ParentID = 1 };
            container.LoadEntities(new Entity[] { gc, ggc });

            Assert.AreSame(ggc, gc.Child);

            gc.Child = null;
            Assert.AreEqual(EntityState.Deleted, ggc.EntityState);
            Assert.IsFalse(ggChildSet.Contains(ggc));

            gc.Child = ggc;
            Assert.AreEqual(EntityState.Unmodified, ggc.EntityState);
            Assert.IsTrue(ggChildSet.Contains(ggc));

            gc.Child = null;
            Assert.AreEqual(EntityState.Deleted, ggc.EntityState);
            Assert.IsFalse(ggChildSet.Contains(ggc));
        }
        private static Parent CreateCompositionHierarchy(int numChildren, int numGrandChildren)
        {
            int parentKey = 1;
            int childKey = 1;
            int grandChildKey = 1;
            int greatGrandChildKey = 1;

            Parent p = new Parent
            {
                ID = parentKey++
            };

            for (int j = 0; j < numChildren; j++)
            {
                Child c = new Child
                {
                    ID = childKey++, ParentID = p.ID, Parent = p
                };
                p.Children.Add(c);
                for (int k = 0; k < numGrandChildren; k++)
                {
                    GrandChild gc = new GrandChild
                    {
                        ID = grandChildKey++, ParentID = c.ID, Parent = c
                    };
                    c.Children.Add(gc);

                    // add singleton child to grand child
                    gc.Child = new GreatGrandChild
                    {
                        ID = greatGrandChildKey++, ParentID = gc.ID, Parent = gc
                    };
                }
            }

            VerifyHierarchy(p);

            return p;
        }
        public void HierarchicalChangeTracking_RejectChanges()
        {
            CompositionScenarios_Explicit ctxt = new CompositionScenarios_Explicit(CompositionScenarios_Explicit_Uri);
            Parent parent = CreateCompositionHierarchy(3, 3);
            ctxt.Parents.Attach(parent);

            // make some changes
            Child child = parent.Children.ToArray()[1];
            GrandChild grandChild = child.Children.First();
            GreatGrandChild greatGrandChild = grandChild.Child;

            greatGrandChild.OperationResult += "x";  // edit
            GrandChild addedGrandChild = new GrandChild();
            child.Children.Add(addedGrandChild);    // add
            GreatGrandChild removedGreatGrandChild = child.Children.ToArray()[1].Child;
            child.Children.ToArray()[1].Child = null;          // remove
            EntityChangeSet cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.AddedEntities.Count == 1 && cs.ModifiedEntities.Count == 5 && cs.RemovedEntities.Count == 1);

            // call reject at various levels of the hierarchy and verify
            // undo the delete of the GreatGrandChild's Child (an edit and a remove undone)
            ((IRevertibleChangeTracking)child.Children.ToArray()[1]).RejectChanges();
            cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.AddedEntities.Count == 1 && cs.ModifiedEntities.Count == 4 && cs.RemovedEntities.Count == 0);

            // ensure reference was reestablished
            Assert.AreSame(child.Children.ToArray()[1], removedGreatGrandChild.Parent);  

            // undo the edit to the GreatGrandChild (2 edits undone)
            ((IRevertibleChangeTracking)greatGrandChild).RejectChanges();
            cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.AddedEntities.Count == 1 && cs.ModifiedEntities.Count == 2 && cs.RemovedEntities.Count == 0);

            // undo the add to the Child's Children collection (1 add and remaining 2 edits undone)
            ((IRevertibleChangeTracking)child).RejectChanges();
            Assert.IsFalse(child.Children.Contains(addedGrandChild));
            Assert.AreEqual(EntityState.Detached, addedGrandChild.EntityState);
            cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.IsEmpty);

            VerifyHierarchy(parent);
        }
        /// <summary>
        /// Create a 4 level compositional hierarchy that includes both
        /// collection and singleton compositions
        /// </summary>
        public static List<Parent> CreateCompositionHierarchy()
        {
            int parentKey = 1;
            int childKey = 1;
            int grandChildKey = 1;
            int greatGrandChildKey = 1;

            List<Parent> parents = new List<Parent>();
            for (int i = 0; i < 3; i++)
            {
                Parent p = new Parent
                {
                    ID = parentKey++
                };
                parents.Add(p);
                for (int j = 0; j < 3; j++)
                {
                    Child c = new Child
                    {
                        ID = childKey++, ParentID = p.ID, Parent = p
                    };
                    p.Children.Add(c);
                    for (int k = 0; k < 3; k++)
                    {
                        GrandChild gc = new GrandChild
                        {
                            ID = grandChildKey++, ParentID = c.ID, Parent = c
                        };
                        c.Children.Add(gc);

                        // add singleton child to grand child
                        gc.Child = new GreatGrandChild
                        {
                            ID = greatGrandChildKey++, ParentID = gc.ID, Parent = gc
                        };
                    }
                }
            }

            return parents;
        }
        public void InsertGrandChild(GrandChild grandChild)
        {
            SetOperationInvoked(grandChild);

            ((CompositionEntityBase)grandChild).OperationResult = "Insert";
        }
        [WorkItem(188918)]  // CSDMain
        public void HierarchicalChangeTracking_AcceptChanges_MultipleChildChanges()
        {
            CompositionScenarios_Explicit ctxt = new CompositionScenarios_Explicit(CompositionScenarios_Explicit_Uri);
            Parent parent = CreateCompositionHierarchy(3, 3);
            ctxt.Parents.Attach(parent);

            // update the child first
            Child child = parent.Children.First();
            child.OperationResult = "complete";
            // update the grandchild
            child.Children.First().OperationResult = "complete";
            // add a new grandchild
            GrandChild newGrandChild = new GrandChild { ID = 25 };
            child.Children.Add(newGrandChild);

            // the key to this bug is accepting the child changes BEFORE
            // the grand child changes.
            ((IChangeTracking)child).AcceptChanges();
            ((IChangeTracking)newGrandChild).AcceptChanges();

            EntityChangeSet cs = ctxt.EntityContainer.GetChanges();
            Assert.IsTrue(cs.IsEmpty);
            Assert.AreEqual(EntityState.Unmodified, child.EntityState);
            Assert.AreEqual(EntityState.Unmodified, newGrandChild.EntityState);
        }
Exemplo n.º 18
0
 public void CustomOp_GrandChild(GrandChild grandChild)
 {
     this.SetOperationInvoked(grandChild, "CustomOp_GrandChild");
     ((CompositionEntityBase)grandChild).OperationResult += ",CustomOp_GrandChild";
 }
 private void AttachChildren(GrandChild entity)
 {
     entity.Parent = this;
 }
 private void DetachChildren(GrandChild entity)
 {
     entity.Parent = null;
 }
 private bool FilterChildren(GrandChild entity)
 {
     return (entity.ParentID == this.ID);
 }
Exemplo n.º 22
0
        public void UpdateGrandChild(GrandChild grandChild)
        {
            SetOperationInvoked(grandChild);

            ((CompositionEntityBase)grandChild).OperationResult = "Update";
        }
        public void Changeset_GetAssociatedChanges_Singleton()
        {
            DomainServiceDescription dsd = DomainServiceDescription.GetDescription(typeof(CompositionScenarios_Explicit));

            // verify singleton change of None
            GreatGrandChild unmodifiedGgc = new GreatGrandChild();
            GrandChild currGrandChild = new GrandChild
            {
                Child = unmodifiedGgc
            };
            GrandChild origGrandChild = new GrandChild
            {
                Child = unmodifiedGgc
            };
            ChangeSetEntry gcOperation = new ChangeSetEntry(1, currGrandChild, origGrandChild, DomainOperation.Update);
            gcOperation.Associations = new Dictionary<string, int[]> { { "Child", new int[] { 2 } } };
            ChangeSetEntry ggcOperation = new ChangeSetEntry(2, unmodifiedGgc, null, DomainOperation.None);
            ChangeSet cs = new ChangeSet(new ChangeSetEntry[] { gcOperation, ggcOperation });
            GreatGrandChild ggcChange = cs.GetAssociatedChanges(currGrandChild, p => p.Child, ChangeOperation.None).Cast<GreatGrandChild>().SingleOrDefault();
            Assert.AreSame(unmodifiedGgc, ggcChange);

            // verify singleton insert
            GreatGrandChild newGgc = new GreatGrandChild();
            currGrandChild = new GrandChild
            {
                Child = newGgc
            };
            origGrandChild = new GrandChild
            {
                Child = null
            };
            gcOperation = new ChangeSetEntry(1, currGrandChild, origGrandChild, DomainOperation.Update);
            gcOperation.Associations = new Dictionary<string, int[]> { { "Child", new int[] { 2 } } };
            ggcOperation = new ChangeSetEntry(2, newGgc, null, DomainOperation.Insert);
            cs = new ChangeSet(new ChangeSetEntry[] { gcOperation, ggcOperation });
            ggcChange = cs.GetAssociatedChanges(currGrandChild, p => p.Child, ChangeOperation.Insert).Cast<GreatGrandChild>().SingleOrDefault();
            Assert.AreSame(newGgc, ggcChange);
            Assert.AreEqual(ChangeOperation.Insert, cs.GetChangeOperation(newGgc));

            // verify singleton update
            GreatGrandChild modifiedGgc = new GreatGrandChild();
            currGrandChild = new GrandChild
            {
                Child = modifiedGgc
            };
            origGrandChild = new GrandChild
            {
                Child = modifiedGgc
            };
            gcOperation = new ChangeSetEntry(1, currGrandChild, origGrandChild, DomainOperation.Update);
            gcOperation.Associations = new Dictionary<string, int[]> { { "Child", new int[] { 2 } } };
            ggcOperation = new ChangeSetEntry(2, modifiedGgc, unmodifiedGgc, DomainOperation.Update);
            cs = new ChangeSet(new ChangeSetEntry[] { gcOperation, ggcOperation });
            ggcChange = cs.GetAssociatedChanges(currGrandChild, p => p.Child, ChangeOperation.Update).Cast<GreatGrandChild>().SingleOrDefault();
            Assert.AreSame(modifiedGgc, ggcChange);
            Assert.AreSame(unmodifiedGgc, cs.GetOriginal(modifiedGgc));
            Assert.AreEqual(ChangeOperation.Update, cs.GetChangeOperation(modifiedGgc));

            // verify singleton delete
            GreatGrandChild deletedGgc = new GreatGrandChild();
            currGrandChild = new GrandChild
            {
                Child = null
            };
            origGrandChild = new GrandChild
            {
                Child = deletedGgc
            };
            gcOperation = new ChangeSetEntry(1, currGrandChild, null, DomainOperation.Update);
            gcOperation.OriginalAssociations = new Dictionary<string, int[]>() { { "Child", new int[] { 2 } } };
            ggcOperation = new ChangeSetEntry(2, deletedGgc, null, DomainOperation.Delete);
            gcOperation.OriginalAssociations = new Dictionary<string, int[]>() { { "Child", new int[] { 2 } } };
            cs = new ChangeSet(new ChangeSetEntry[] { gcOperation, ggcOperation });
            ggcChange = cs.GetAssociatedChanges(currGrandChild, p => p.Child, ChangeOperation.Delete).Cast<GreatGrandChild>().SingleOrDefault();
            Assert.AreSame(deletedGgc, ggcChange);
            Assert.AreSame(null, cs.GetOriginal(deletedGgc));
            Assert.AreEqual(ChangeOperation.Delete, cs.GetChangeOperation(deletedGgc));
        }