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());
        }
Example #5
0
        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);
        }
Example #6
0
        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;
 }
Example #8
0
        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);
        }
Example #9
0
        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();
        }
Example #10
0
        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();
        }
Example #11
0
        // 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;
        }
Example #12
0
        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);
        }
Example #13
0
        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);
        }
Example #14
0
        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));
        }
Example #15
0
 public static Hierarchy CreateHierarchy(this ChangeSetBuilder pendingChanges)
 {
     return(pendingChanges
            .AddCommandAndPreviewTarget <Hierarchy>(new CreateHierarchyCommand()));
 }
Example #16
0
 public static Unit CreateUnit(this ChangeSetBuilder pendingChanges, string name, Address address)
 {
     return(pendingChanges
            .AddCommandAndPreviewTarget <Unit>(new CreateUnitCommand(name, address)));
 }
Example #17
0
        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);
        }
Example #18
0
 private static void EnsureDetachedFromFormerParent(HierarchyNode hierarchyNode, ChangeSetBuilder pendingChanges)
 {
     if (hierarchyNode.Parent != null)
     {
         pendingChanges.Add(new DetachChildCommand(hierarchyNode.Parent.Id, hierarchyNode.Id));
     }
 }