/// <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; } }