Example #1
0
        public void FullUpdate() //Lots of tests with updating
        {
            var package            = SimplePackage();
            var originaPackageCopy = new EntityPackage(package);

            service.InsertWithHistoryAsync(package, 1).Wait();

            var firstInsertedPackage = new EntityPackage(package);

            package.Relations.First().value = "Something NEW";
            package.Values.First().value    = "aha MORE";

            service.UpdateWithHistoryAsync(package, 1).Wait();

            //This shouldn't be "new", it should be the same as before
            Assert.Equal(firstInsertedPackage.Entity.id, package.Entity.id);

            var revisions = service.GetRevisionIdsAsync(package.Entity.id).Result;

            Assert.Single(revisions);
            Assert.NotEqual(package.Entity.id, revisions.First());

            //Ensure the CURRENT package we pulled out is EXACTLY the same (minus date kind)
            var currentPackage = provider.FindByIdAsync(package.Entity.id).Result;

            Assert.Equal(package, currentPackage);

            //Ensure the package from history is EXACTLY the same as the one before sans ids (set all to 0)
            var revisionPackage = provider.FindByIdAsync(revisions.First()).Result;
            var likeUpdate      = service.ConvertHistoryToUpdate(revisionPackage);

            Assert.Equal(firstInsertedPackage, likeUpdate);
        }
        /// <summary>
        /// Update the given existing entity with the new entity, preserving the history for the original.
        /// </summary>
        /// <param name="updateData"></param>
        /// <param name="originalData"></param>
        /// <returns></returns>
        public async Task UpdateWithHistoryAsync(EntityPackage updateData, long user, EntityPackage originalData = null)
        {
            logger.LogTrace($"WriteHistoric called for entity {updateData.Entity.id}");

            //The original isn't necessary; we can find it using the id from our apparently updated data
            if (originalData == null)
            {
                originalData = await provider.FindByIdAsync(updateData.Entity.id);
            }

            var history = await CreateHistoricCopyAsync(originalData.Entity);

            try
            {
                //Bring all the existing over to this historic entity
                history.Relink(originalData.Values, originalData.Relations);

                //WE have to link the new stuff to US because we want to write everything all at once
                originalData.Entity.Relink(updateData.Values, updateData.Relations);

                //Add the historic link back to the history copy from the
                originalData.Relations.Add(NewHistoryLink(updateData.Entity, history));

                //A special thing: the values and relations need to be NEW for the update data
                updateData.Relations.ForEach(x => x.id = 0);
                updateData.Values.ForEach(x => x.id    = 0);

                //We're writing the entirety of the "update" data.
                var writes = updateData.FlattenPackage();

                //Also writing the relinked original stuff.
                writes.AddRange(originalData.Values);
                writes.AddRange(originalData.Relations);

                writes.Add(activityService.MakeActivity(updateData.Entity, user, Keys.UpdateAction, history.id.ToString()));

                await provider.WriteAsync(writes.ToArray());
            }
            catch
            {
                logger.LogError("Failure during historic update, trying to undo... Exception bubbling...");
                await provider.DeleteAsync(history);

                throw;
            }
        }