public async Task <object> Save([FromBody] JObject diffJson)
        {
            //WARNING: This sample implementation bypasses locking, versioning and subscriptions. If you use it side by side with
            //the RetroDRY implementation, changes saved here won't be noticed by RetroDRY clients.

            //authenticate; for demo purposes we will assume the user, but for a real app you would check the authentication
            //header and look up the user in a cache or databse
            var user = UserCache.Buffy_The_Admin;

            //parse the changes provided by the caller
            var diff = Retrovert.FromDiff(Globals.Retroverse.DataDictionary, diffJson);

            //save
            MultiSaver.Result[] saveresult;
            using (var saver = new MultiSaver(Globals.Retroverse, user, new[] { diff }))
            {
                await saver.Save();

                saveresult = saver.GetResults();
            }

            return(new
            {
                Key = saveresult[0].NewKey.ToString(),
                saveresult[0].Errors
            });
        }
        public void FromDiff()
        {
            var emily = new Ogre()
            {
                Name          = "Emily",
                Key           = new PersistonKey("Ogre", "3", false),
                Version       = "v2",
                Money         = 2,
                OgreId        = 3,
                PaymentMethod = new List <Ogre.PaymentMethodRow>
                {
                    new Ogre.PaymentMethodRow {
                        PaymentMethodId = 91, Method = "THUMP", Notes = "n1"
                    },
                    new Ogre.PaymentMethodRow {
                        PaymentMethodId = 92, Method = "BOP", Notes = null
                    }
                }
            };

            var ddict = new DataDictionary();

            ddict.AddDatonUsingClassAnnotation(typeof(Ogre));

            string json         = "{'key':'Ogre|=9','version':'v2','ogre':[{'ogreId':9,'money':2.50,'paymentMethod-deleted':[{'paymentMethodId':92}],'paymentMethod-new':[{'method':'STOMP','notes':'n2'}]}]}".Replace('\'', '"');
            var    jobj         = JsonConvert.DeserializeObject <JObject>(json);
            var    emilyChanges = Retrovert.FromDiff(ddict, jobj);

            Assert.AreEqual(new PersistonKey("Ogre", "9", false), emilyChanges.Key);
            Assert.AreEqual("v2", emilyChanges.BasedOnVersion);
            Assert.AreEqual(9, emilyChanges.MainTable[0].Columns["OgreId"]);
            Assert.AreEqual((decimal)2.5, emilyChanges.MainTable[0].Columns["Money"]);

            emilyChanges.ApplyTo(ddict.DatonDefs["Ogre"], emily);
            Assert.AreEqual((decimal)2.5, emily.Money);
            Assert.IsFalse(emily.PaymentMethod.Any(m => m.Method == "BOP"));  //deleted BOP
            Assert.IsTrue(emily.PaymentMethod.Any(m => m.Method == "STOMP")); //added STOMP
            Assert.IsTrue(emily.PaymentMethod.Any(m => m.Method == "THUMP")); //no change
        }