/// <summary> /// Invokes the 'CustomOp_Child' method of the specified <see cref="Child"/> entity. /// </summary> /// <param name="child">The <see cref="Child"/> entity instance.</param> public void CustomOp_Child(Child child) { child.CustomOp_Child(); }
public void CustomOp_Child(Child child) { ((CompositionEntityBase)child).OperationResult += ",CustomOp_Child"; }
private void DetachChildren(Child entity) { entity.Parent = null; }
private bool FilterChildren(Child entity) { return (entity.ParentID == this.ID); }
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; }
private void AttachChildren(Child entity) { entity.Parent = this; }
/// <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(); }
/// <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 Entity_RemoveParent() { ConfigurableEntityContainer container = new ConfigurableEntityContainer(); container.CreateSet<Parent>(EntitySetOperations.All); container.CreateSet<Child>(EntitySetOperations.All); container.CreateSet<GrandChild>(EntitySetOperations.All); EntitySet<Parent> parentSet = container.GetEntitySet<Parent>(); EntitySet<Child> childSet = container.GetEntitySet<Child>(); Parent parent1 = new Parent() { ID = 1 }; Parent parent2 = new Parent() { ID = 2 }; Child child = new Child() { 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."); parentSet.Remove(parent1); EntityChangeSet changeSet = container.GetChanges(); Assert.AreEqual(2, changeSet.Count()); }
public void Composition_DeleteAndAddChildWithSameKey() { CompositionScenarios_Explicit ctx = new CompositionScenarios_Explicit(CompositionScenarios_Explicit_Uri); LoadOperation lo = ctx.Load(ctx.GetParentsQuery(), false); SubmitOperation so = null; int childID = 0; int parentID = 0; EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { TestHelperMethods.AssertOperationSuccess(lo); // Find any parent and delete a child. Parent parent = ctx.Parents.First(); Child child = parent.Children.First(); parent.Children.Remove(child); // Add a new child with the same key as the one deleted. Child newChild = new Child { ID = child.ID, ParentID = child.ParentID, Parent = child.Parent, Property = "NewProp" }; parent.Children.Add(newChild); // Save the parent and child keys so that we can check later if the child got added properly. childID = child.ID; parentID = parent.ID; so = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null); }); EnqueueConditional(() => so.IsComplete); EnqueueCallback(delegate { Assert.IsFalse(so.HasError); Assert.IsFalse(ctx.HasChanges); // Reload the entities. ctx.EntityContainer.Clear(); lo = ctx.Load(ctx.GetParentsQuery(), false); }); EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { TestHelperMethods.AssertOperationSuccess(lo); // Make sure the new child got added properly. Parent parent1 = ctx.Parents.Where(p => p.ID == parentID).SingleOrDefault(); Assert.IsNotNull(parent1); Assert.IsNotNull(parent1.Children.Where(c => c.ID == childID && c.Property == "NewProp")); }); EnqueueTestComplete(); }
public void Composition_InvalidParentUpdate_EntityCollection() { ConfigurableEntityContainer container = new ConfigurableEntityContainer(); container.CreateSet<Parent>(EntitySetOperations.All); container.CreateSet<Child>(EntitySetOperations.All); container.CreateSet<GrandChild>(EntitySetOperations.All); EntitySet<Parent> parentSet = container.GetEntitySet<Parent>(); EntitySet<Child> childSet = container.GetEntitySet<Child>(); Parent parent1 = new Parent() { ID = 1 }; Parent parent2 = new Parent() { ID = 2 }; Child child = new Child() { 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_ParentUpdateOnDelete() { ConfigurableEntityContainer container = new ConfigurableEntityContainer(); container.CreateSet<Parent>(EntitySetOperations.All); container.CreateSet<Child>(EntitySetOperations.All); container.CreateSet<GrandChild>(EntitySetOperations.All); EntitySet<Parent> parentSet = container.GetEntitySet<Parent>(); EntitySet<Child> childSet = container.GetEntitySet<Child>(); Parent parent1 = new Parent() { ID = 1 }; Child child1 = new Child() { ID = 1, Parent = parent1 }; container.LoadEntities(new Entity[] { parent1, child1 }); // insert new parent and child Parent newParent = new Parent(); Child newChild = new Child(); newChild.Parent = newParent; parentSet.Add(newParent); // When the parent is removed, all it's children are also removed. // This causes the child ParentID to be set to 0, which means it now // matches the new Parent.Children collection. The removed child is added to // the new parent's collection, which causes child.Parent to be updated. // However that add is transitory - once the child is removed from the // entity set, it is removed from the new entity's child collection. // That invalid update will result in an exception on submit. parentSet.Remove(parent1); Assert.AreEqual(1, newParent.Children.Count); Assert.IsTrue(newParent.Children.Contains(newChild)); // if we allow the transitory phase, on accept changes we have to be // sure things are fixed up Assert.AreEqual(EntityState.Deleted, parent1.EntityState); Assert.AreEqual(EntityState.Deleted, child1.EntityState); Assert.AreSame(newParent, newChild.Parent); // changeset validation succeeds, since the parent is deleted along // with the child EntityChangeSet changeSet = container.GetChanges(); Assert.IsTrue(changeSet.AddedEntities.Count == 2 && changeSet.RemovedEntities.Count == 2); ChangeSetBuilder.CheckForInvalidUpdates(changeSet); }
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)); }
public void InsertChild(Child child) { SetOperationInvoked(child); ((CompositionEntityBase)child).OperationResult = "Insert"; }
public void HierarchicalChangeTracking_RejectChanges_Bug799365() { CompositionScenarios_Explicit ctxt = new CompositionScenarios_Explicit(CompositionScenarios_Explicit_Uri); Parent parent = CreateCompositionHierarchy(3, 3); ctxt.Parents.Attach(parent); // add a new child then reject changes Child newChild = new Child { ID = 25 }; parent.Children.Add(newChild); EntityChangeSet cs = ctxt.EntityContainer.GetChanges(); Assert.IsTrue(cs.AddedEntities.Count == 1 && cs.ModifiedEntities.Count == 1); ctxt.RejectChanges(); cs = ctxt.EntityContainer.GetChanges(); Assert.IsTrue(cs.IsEmpty); Assert.AreEqual(EntityState.Detached, newChild.EntityState); }
public void DeleteChild(Child child) { SetOperationInvoked(child); ((CompositionEntityBase)child).OperationResult = "Delete"; }
private bool FilterParent(Child entity) { return (entity.ID == this.ParentID); }
public void CustomOp_Child(Child child) { this.SetOperationInvoked(child, "CustomOp_Child"); ((CompositionEntityBase)child).OperationResult += ",CustomOp_Child"; }
public void Composition_AddChildPreviouslyReferencingOtherParent() { 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 p1 = new Parent() { ID = 1 }; Parent p2 = new Parent() { ID = 2 }; container.LoadEntities(new Entity[] { p1, p2 }); Child child = new Child() { ID = 1, ParentID = 2 }; p1.Children.Add(child); Assert.AreEqual(EntityState.Modified, p1.EntityState); Assert.IsTrue(childSet.HasChanges); }