public void Parent_and_child() { ObjectId hierarchyId; var builder = new ChangeSetBuilder(objectFacade, null); { var hierarchy = builder.CreateHierarchy(); hierarchyId = hierarchy.Id; var parentUnit = builder.CreateUnit("Parent", new Address("Lubicz", "23", "Krakow", "PL")); var childUnit = builder.CreateUnit("Child", null); builder.SetHierarchyRoot(hierarchy, parentUnit); builder.SetParent(hierarchy, childUnit, parentUnit); } var view = objectFacade.GetSnapshot(builder.PendingChanges); { var hierarchy = view.GetById<Hierarchy>(hierarchyId); var rootUnit = hierarchy.RootUnit; var childUnits = hierarchy.RootUnit.GetChildrenWithin(hierarchy); var firstChildUnit = childUnits.First(); Assert.AreEqual("Parent", rootUnit.Name); Assert.AreEqual(new Address("Lubicz", "23", "Krakow", "PL"), rootUnit.Address); Assert.AreEqual("Child", firstChildUnit.Name); var allUnits = view.List<Unit>().ToList(); Assert.AreEqual(2, allUnits.Count()); } }
public void Parent_and_child() { ObjectId hierarchyId; var builder = new ChangeSetBuilder(objectFacade, null); { var hierarchy = builder.CreateHierarchy(); hierarchyId = hierarchy.Id; var parentUnit = builder.CreateUnit("Parent", new Address("Lubicz", "23", "Krakow", "PL")); var childUnit = builder.CreateUnit("Child", null); builder.SetHierarchyRoot(hierarchy, parentUnit); builder.SetParent(hierarchy, childUnit, parentUnit); } var view = objectFacade.GetSnapshot(builder.PendingChanges); { var hierarchy = view.GetById <Hierarchy>(hierarchyId); var rootUnit = hierarchy.RootUnit; var childUnits = hierarchy.RootUnit.GetChildrenWithin(hierarchy); var firstChildUnit = childUnits.First(); Assert.AreEqual("Parent", rootUnit.Name); Assert.AreEqual(new Address("Lubicz", "23", "Krakow", "PL"), rootUnit.Address); Assert.AreEqual("Child", firstChildUnit.Name); var allUnits = view.List <Unit>().ToList(); Assert.AreEqual(2, allUnits.Count()); } }
private static void EnsureDetachedFromFormerParent(HierarchyNode hierarchyNode, ChangeSetBuilder pendingChanges) { if (hierarchyNode.Parent != null) { pendingChanges.Add(new DetachChildCommand(hierarchyNode.Parent.Id, hierarchyNode.Id)); } }
public async Task SubmitAsync_Exceptions() { var mockDomainClient = new CitiesMockDomainClient(); Cities.CityDomainContext ctx = new Cities.CityDomainContext(mockDomainClient); DomainOperationException ex = new DomainOperationException("Submit Failed!", OperationErrorStatus.ServerError, 42, "StackTrace"); // If cancellation results in request beeing cancelled the result should be cancelled mockDomainClient.SubmitCompletedResult = Task.FromException <SubmitCompletedResult>(ex); ctx.Cities.Add(new City() { Name = "NewCity", StateName = "NN", CountyName = "NewCounty" }); Assert.IsTrue(ctx.EntityContainer.HasChanges); var submitEx = await ExceptionHelper.ExpectExceptionAsync <SubmitOperationException>(() => ctx.SubmitChangesAsync()); // verify the exception properties Assert.AreEqual(string.Format(Resource.DomainContext_SubmitOperationFailed, ex.Message), submitEx.Message); Assert.AreEqual(ex.StackTrace, submitEx.StackTrace); Assert.AreEqual(ex.Status, submitEx.Status); Assert.AreEqual(ex.ErrorCode, submitEx.ErrorCode); Assert.IsTrue(ctx.EntityContainer.HasChanges); // now test with validation exception var changeSet = ctx.EntityContainer.GetChanges(); IEnumerable <ChangeSetEntry> entries = ChangeSetBuilder.Build(changeSet); ChangeSetEntry entry = entries.First(); entry.ValidationErrors = new ValidationResultInfo[] { new ValidationResultInfo("Foo", new string[] { "Bar" }) }; mockDomainClient.SubmitCompletedResult = Task.FromResult(new SubmitCompletedResult(changeSet, entries)); submitEx = await ExceptionHelper.ExpectExceptionAsync <SubmitOperationException>(() => ctx.SubmitChangesAsync()); // verify the exception properties Assert.AreEqual(Resource.DomainContext_SubmitOperationFailed_Validation, submitEx.Message); Assert.AreEqual(OperationErrorStatus.ValidationFailed, submitEx.Status); Assert.AreEqual(1, submitEx.EntitiesInError.Count); Assert.AreEqual(entry.ClientEntity, submitEx.EntitiesInError.First()); // now test again with conflicts entries = ChangeSetBuilder.Build(changeSet); entry = entries.First(); entry.ConflictMembers = new string[] { nameof(City.CountyName) }; entry.StoreEntity = new City() { CountyName = "OtherCounty" }; mockDomainClient.SubmitCompletedResult = Task.FromResult(new SubmitCompletedResult(changeSet, entries)); submitEx = await ExceptionHelper.ExpectExceptionAsync <SubmitOperationException>(() => ctx.SubmitChangesAsync()); // verify the exception properties Assert.AreEqual(Resource.DomainContext_SubmitOperationFailed_Conflicts, submitEx.Message); Assert.AreEqual(OperationErrorStatus.Conflicts, submitEx.Status); Assert.AreEqual(1, submitEx.EntitiesInError.Count); Assert.AreEqual(entry.ClientEntity, submitEx.EntitiesInError.First()); }
public void TestAssociations_UpdatedReferencingNew() { NorthwindEntityContainer ec = new NorthwindEntityContainer(); Product p1 = new Product { ProductID = 1, CategoryID = 1 }; Product p2 = new Product { ProductID = 2, CategoryID = 2 }; Category c1 = new Category { CategoryID = 1 }; Category c2 = new Category { CategoryID = 2 }; ec.LoadEntities(new Entity[] { p1, p2, c1, c2 }); // take two existing parents (the FK side of the association) // access their existing children Category prevCat = p1.Category; Assert.IsNotNull(prevCat); prevCat = p2.Category; Assert.IsNotNull(prevCat); // create two new children Category newCat1 = new Category { CategoryID = 3 }; Category newCat2 = new Category { CategoryID = 4 }; // assign the two new children p1.Category = newCat1; p2.Category = newCat2; EntityChangeSet cs = ec.GetChanges(); Assert.AreEqual(2, cs.AddedEntities.Count); Assert.AreEqual(2, cs.ModifiedEntities.Count); List <ChangeSetEntry> entries = ChangeSetBuilder.Build(cs); ChangeSetEntry entry = entries.Single(p => p.Entity == p1); // the bug was that we weren't populating the association map in this // scenario since previously we required BOTH parent and child to be new. // We've relaxed that to ensure that if the child is new, the association // shows up in the map. Assert.IsNotNull(entry.Associations); int[] ids = entry.Associations["Category"]; Category referenced = (Category)entries.Single(p => p.Id == ids.Single()).Entity; Assert.AreSame(newCat1, referenced); }
public static void SetParent(this ChangeSetBuilder pendingChanges, Hierarchy hierarchy, Unit target, Unit newParent) { var parentHierarchyNode = EnsureIsPartOfHierarchy(newParent, hierarchy, pendingChanges); var hierarchyNode = EnsureIsPartOfHierarchy(target, hierarchy, pendingChanges); EnsureDetachedFromFormerParent(hierarchyNode, pendingChanges); pendingChanges .Add(new AttachChildCommand(parentHierarchyNode.Id, hierarchyNode.Id)) .Add(new SetParentCommand(hierarchyNode.Id, parentHierarchyNode.Id)); }
private static HierarchyNode EnsureIsPartOfHierarchy(Unit target, Hierarchy hierarchy, ChangeSetBuilder pendingChanges) { var hierarchyNode = target.Nodes.SingleOrDefault(x => x.Context.Id == hierarchy.Id); if (hierarchyNode == null) { var nodeId = ObjectId.NewUniqueId(); return pendingChanges .Add(new AttachToHierarchyCommand(target.Id, nodeId)) .Add(new CreateHierarchyNodeCommand(nodeId, target.Id, hierarchy.Id)) .GetPreview() .GetById<HierarchyNode>(nodeId); } return hierarchyNode; }
public void ChangeSet_DontLoadUnloadedAssociations() { NorthwindEntityContainer entities = new NorthwindEntityContainer(); EntitySet <Order> orders = entities.GetEntitySet <Order>(); EntitySet <Order_Detail> details = entities.GetEntitySet <Order_Detail>(); // add a few existing entities Order order = new Order { OrderID = 1 }; Order_Detail detail = new Order_Detail { OrderID = 1, ProductID = 1 }; entities.LoadEntities(new Entity[] { order, detail }); // modify both entities order.Freight = 5; detail.Quantity = 5; IEntityRef er = detail.GetEntityRef("Order"); Assert.IsNull(er); IEntityCollection ec = order.Order_Details; Assert.IsFalse(ec.HasValues); EntityChangeSet cs = entities.GetChanges(); Assert.AreEqual(2, cs.ModifiedEntities.Count); // after computing the changeset, no association members // should have been loaded er = detail.GetEntityRef("Order"); Assert.IsNull(er); Assert.IsFalse(ec.HasValues); // after building the operation list, no association members // should have been loaded ChangeSetBuilder.Build(cs); er = detail.GetEntityRef("Order"); Assert.IsNull(er); Assert.IsFalse(ec.HasValues); }
public void Composition_Inheritance_Add_Derived_Child_To_Derived_Parent() { CompositionInheritanceScenarios ctxt = new CompositionInheritanceScenarios(CompositionInheritanceScenarios_Uri); CI_SpecialParent parent = null; SubmitOperation so = null; IEnumerable <Entity> expectedUpdates = null; LoadOperation lo = ctxt.Load(ctxt.GetParentsQuery(), false); EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { TestHelperMethods.AssertOperationSuccess(lo); parent = ctxt.CI_Parents.OfType <CI_SpecialParent>().First(); CI_AdoptedChild newChild = new CI_AdoptedChild() { Age = 5, }; parent.Children.Add(newChild); Assert.AreSame(parent, ((Entity)newChild).Parent); EntityChangeSet cs = ctxt.EntityContainer.GetChanges(); Assert.IsTrue(cs.ModifiedEntities.Count == 1, "wrong modified count"); Assert.IsTrue(cs.AddedEntities.Count == 1, "wrong added count"); Assert.IsTrue(cs.RemovedEntities.Count == 0, "wrong removed count"); Assert.IsTrue(cs.ModifiedEntities.Contains(parent)); Assert.IsTrue(cs.AddedEntities.Contains(newChild)); // verify that original associations are set up correctly IEnumerable <ChangeSetEntry> entityOps = ChangeSetBuilder.Build(cs); 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); }); EnqueueTestComplete(); }
public void Composition_Inheritance_Update_Base_Child_On_Base_Parent() { CompositionInheritanceScenarios ctxt = new CompositionInheritanceScenarios(CompositionInheritanceScenarios_Uri); CI_Parent parent = null; SubmitOperation so = null; IEnumerable <Entity> expectedUpdates = null; LoadOperation lo = ctxt.Load(ctxt.GetParentsQuery(), false); this.EnqueueCompletion(() => lo); EnqueueCallback(delegate { TestHelperMethods.AssertOperationSuccess(lo); parent = ctxt.CI_Parents.First(p => p.GetType() == typeof(CI_Parent)); CI_Child existingChild = parent.Children.First(c => c.GetType() == typeof(CI_Child)); Assert.AreSame(parent, ((Entity)existingChild).Parent); // update derived comp child existingChild.Age++;; EntityChangeSet cs = ctxt.EntityContainer.GetChanges(); Assert.IsTrue(cs.ModifiedEntities.Count == 2, "wrong modified count"); Assert.IsTrue(cs.RemovedEntities.Count == 0, "wrong removed count"); Assert.IsTrue(cs.ModifiedEntities.Contains(parent)); Assert.IsTrue(cs.ModifiedEntities.Contains(existingChild)); // verify that original associations are set up correctly IEnumerable <ChangeSetEntry> entityOps = ChangeSetBuilder.Build(cs); this.ValidateEntityOperationAssociations(entityOps); expectedUpdates = cs.Where(p => p.HasChildChanges || p.HasPropertyChanges).ToArray(); so = ctxt.SubmitChanges(TestHelperMethods.DefaultOperationAction, null); }); this.EnqueueCompletion(() => so); EnqueueCallback(delegate { this.VerifySuccess(ctxt, so, expectedUpdates); }); EnqueueTestComplete(); }
// Uncomment this test out to do lightweight perf measurement for the submit pipeline //[TestMethod] public void Submit_MeasureChangeset() { CityDomainContext dc = null; int numIterations = 500; DateTime start = DateTime.Now; for (int i = 0; i < numIterations; i++) { dc = new CityDomainContext(TestURIs.Cities); Cities.CityData data = new CityData(); dc.EntityContainer.LoadEntities(data.Cities); foreach (City city in dc.Cities) { city.ZoneID += 1; city.AssignCityZone("z"); } for (int j = 1; j <= 5; j++) { dc.Cities.Add(new City() { Name = "Redmond" + new string('x', j), CountyName = "King", StateName = "WA" }); } // simulate the major changeset operations here EntityChangeSet cs = dc.EntityContainer.GetChanges(); cs.Validate(dc.ValidationContext); ChangeSetBuilder.Build(cs); } DateTime stop = DateTime.Now; TimeSpan ts = stop - start; double avgMs = ts.TotalMilliseconds / numIterations; }
public void UnhandledSubmitOperationError() { CityDomainContext cities = new CityDomainContext(TestURIs.Cities); CityData data = new CityData(); cities.Cities.LoadEntities(data.Cities.ToArray()); City city = cities.Cities.First(); city.ZoneID = 1; Assert.IsTrue(cities.EntityContainer.HasChanges); SubmitOperation submit = new SubmitOperation(cities.EntityContainer.GetChanges(), null, null, null); DomainOperationException expectedException = null; DomainOperationException ex = new DomainOperationException("Submit Failed!", OperationErrorStatus.ServerError, 42, "StackTrace"); try { submit.Complete(ex); } catch (DomainOperationException e) { expectedException = e; } // verify the exception properties Assert.IsNotNull(expectedException); Assert.AreEqual(string.Format(Resource.DomainContext_SubmitOperationFailed, ex.Message), expectedException.Message); Assert.AreEqual(ex.StackTrace, expectedException.StackTrace); Assert.AreEqual(ex.Status, expectedException.Status); Assert.AreEqual(ex.ErrorCode, expectedException.ErrorCode); Assert.AreEqual(false, submit.IsErrorHandled); // now test again with conflicts expectedException = null; IEnumerable <ChangeSetEntry> entries = ChangeSetBuilder.Build(cities.EntityContainer.GetChanges()); ChangeSetEntry entry = entries.First(); entry.ValidationErrors = new ValidationResultInfo[] { new ValidationResultInfo("Foo", new string[] { "Bar" }) }; submit = new SubmitOperation(cities.EntityContainer.GetChanges(), null, null, null); try { submit.Complete(OperationErrorStatus.Conflicts); } catch (DomainOperationException e) { expectedException = e; } // verify the exception properties Assert.IsNotNull(expectedException); Assert.AreEqual(string.Format(Resource.DomainContext_SubmitOperationFailed_Conflicts), expectedException.Message); // now test again with validation errors expectedException = null; entries = ChangeSetBuilder.Build(cities.EntityContainer.GetChanges()); entry = entries.First(); entry.ConflictMembers = new string[] { "ZoneID" }; submit = new SubmitOperation(cities.EntityContainer.GetChanges(), null, null, null); try { submit.Complete(OperationErrorStatus.ValidationFailed); } catch (DomainOperationException e) { expectedException = e; } // verify the exception properties Assert.IsNotNull(expectedException); Assert.AreEqual(string.Format(Resource.DomainContext_SubmitOperationFailed_Validation, ex.Message), expectedException.Message); }
public void TestAssociations_GraphDelete() { NorthwindEntityContainer entities = new NorthwindEntityContainer(); #region Create a test graph Customer cust = new Customer { CustomerID = "ALFKI" }; Order order = new Order { OrderID = 1 }; order.Customer = cust; order.Order_Details.Add(new Order_Detail { ProductID = 1 }); order.Order_Details.Add(new Order_Detail { ProductID = 2 }); order.Order_Details.Add(new Order_Detail { ProductID = 3 }); entities.LoadEntities(new Entity[] { cust, order }); entities.LoadEntities(order.Order_Details); ((IRevertibleChangeTracking)entities).AcceptChanges(); #endregion // now delete the graph // TODO : currently this has to be done in this specific order // with association modifications being done while the parent // is attached (before it is removed from set) foreach (Order_Detail detail in order.Order_Details) { order.Order_Details.Remove(detail); entities.GetEntitySet <Order_Detail>().Remove(detail); } cust.Orders.Remove(order); entities.GetEntitySet <Order>().Remove(order); entities.GetEntitySet <Customer>().Remove(cust); // verify the changeset EntityChangeSet changeSet = entities.GetChanges(); Assert.AreEqual(5, changeSet.RemovedEntities.Count); // build the operation list and verify it List <ChangeSetEntry> operations = ChangeSetBuilder.Build(changeSet); // verify that the association collections for the Order operation are null ChangeSetEntry orderOperation = operations.Single(p => p.Entity == order); ChangeSetEntry custOperation = operations.Single(p => p.Entity == cust); Assert.IsNull(orderOperation.Associations); Assert.IsNull(orderOperation.OriginalAssociations); Assert.IsNotNull(orderOperation.OriginalEntity); // verify that the association collections for the Customer operation are null Assert.IsNull(custOperation.OriginalEntity); Assert.IsNull(custOperation.Associations); Assert.IsNull(custOperation.OriginalAssociations); // verify that deleted OrderDetails have null associations as well ChangeSetEntry detailOperation = operations.First(p => p.Entity.GetType() == typeof(Order_Detail)); Assert.IsNotNull(detailOperation.OriginalEntity); Assert.IsNull(detailOperation.Associations); Assert.IsNull(detailOperation.OriginalAssociations); }
public static void SetHierarchyRoot(this ChangeSetBuilder pendingChanges, Hierarchy hierarchy, Unit newRoot) { var hierarchyNode = EnsureIsPartOfHierarchy(newRoot, hierarchy, pendingChanges); pendingChanges.Add(new SetHierarchyRootCommand(hierarchy.Id, hierarchyNode.Id)); }
public static Hierarchy CreateHierarchy(this ChangeSetBuilder pendingChanges) { return(pendingChanges .AddCommandAndPreviewTarget <Hierarchy>(new CreateHierarchyCommand())); }
public static Unit CreateUnit(this ChangeSetBuilder pendingChanges, string name, Address address) { return(pendingChanges .AddCommandAndPreviewTarget <Unit>(new CreateUnitCommand(name, address))); }
private static HierarchyNode EnsureIsPartOfHierarchy(Unit target, Hierarchy hierarchy, ChangeSetBuilder pendingChanges) { var hierarchyNode = target.Nodes.SingleOrDefault(x => x.Context.Id == hierarchy.Id); if (hierarchyNode == null) { var nodeId = ObjectId.NewUniqueId(); return(pendingChanges .Add(new AttachToHierarchyCommand(target.Id, nodeId)) .Add(new CreateHierarchyNodeCommand(nodeId, target.Id, hierarchy.Id)) .GetPreview() .GetById <HierarchyNode>(nodeId)); } return(hierarchyNode); }