/// <summary> /// Given parsed untyped JSON in diff format, construct a PersistonDiff /// </summary> public static PersistonDiff FromDiff(DataDictionary dbdef, JObject jroot) { var datonKey = DatonKey.Parse(jroot.Value <string>("key")); var datondef = dbdef.FindDef(datonKey); var diff = new PersistonDiff(datondef, datonKey, jroot.Value <string>("version")); ReadJsonDiffRowArray(jroot, datondef.MainTableDef, diff.MainTable); //existing single-main-row diffs might not include the primary key in the main row, so add it here if (!datondef.MultipleMainRows) { var mainDiffRow = diff.MainTable.First(); if (!mainDiffRow.Columns.ContainsKey(datondef.MainTableDef.PrimaryKeyColName)) { var pkColdef = datondef.MainTableDef.FindCol(datondef.MainTableDef.PrimaryKeyColName); var pk = Utils.ChangeType(((PersistonKey)datonKey).PrimaryKey, pkColdef.CSType); mainDiffRow.Columns[datondef.MainTableDef.PrimaryKeyColName] = pk; } } return(diff); }
/// <summary> /// Return readable strings describing any disallowed writes for this user /// </summary> /// <param name="pristineDaton">null for new unsaved persistons, else the pristine version being edited</param> public IEnumerable <string> GetDisallowedWrites(Daton pristineDaton, DatonDef datondef, PersistonDiff diff) { var errors = new List <string>(); FindDisallowedWrites(errors, pristineDaton, datondef.MainTableDef, diff.MainTable); return(errors); }
/// <summary> /// Save persiston to database /// </summary> /// <param name="pristineDaton">null or the version before the diff was applied</param> /// <param name="modifiedDaton">the validated final version</param> /// <param name="diff">the difference between pristine and modified, which is what this method inspects to make the changes</param> public virtual async Task Save(IDbConnection db, IUser user, Persiston pristineDaton, Persiston modifiedDaton, PersistonDiff diff) { //called for each row in traversal; return true to recurse over children async Task <(object, bool)> rowCallback(RowChangingData cdata) { if (cdata.DiffRow.Kind == DiffKind.DeletedRow) { await DeleteRowWithCascade(db, cdata.TableDef, cdata.PristineRow); return(null, false); //don't recur to children of deleted row } object newpk = await InsertUpdateRow(db, cdata); return(newpk, true); } var tdata = new TraversalData { ParentKey = null, TableDef = diff.DatonDef.MainTableDef, DiffRowList = diff.MainTable, PristineList = null, ModifiedList = null, ProcessRowF = rowCallback }; if (diff.DatonDef.MultipleMainRows) { var mainListField = diff.DatonDef.Type.GetField(tdata.TableDef.Name); tdata.PristineList = mainListField.GetValue(pristineDaton) as IList; tdata.ModifiedList = mainListField.GetValue(modifiedDaton) as IList; await TraverseDiffList(tdata, null, null); } else { await TraverseDiffList(tdata, pristineDaton, modifiedDaton); } }