/// <summary> /// Saves a storable object in the database. /// </summary> /// <param name="obj">Storable object to save.</param> /// <param name="db">Database.</param> /// <param name="context">Serialization context.</param> /// <param name="saveChildren">If set to <c>false</c>, <see cref="IStorable"/> children are not saved.</param> internal static void SaveObject(IStorable obj, Database db, SerializationContext context = null, bool saveChildren = true) { if (context == null) { context = new SerializationContext(db, obj.GetType()); if (obj.ParentID != Guid.Empty) { context.RootID = obj.ParentID; } else { context.RootID = obj.ID; } } context.SaveChildren = saveChildren; context.Stack.Push(obj); Document doc = db.GetDocument(DocumentsSerializer.StringFromID(obj.ID, context.RootID)); doc.Update((UnsavedRevision rev) => { JObject jo = SerializeObject(obj, rev, context); IDictionary <string, object> props = jo.ToObject <IDictionary <string, object> > (); /* SetProperties sets a new properties dictionary, removing the attachments we * added in the serialization */ if (rev.Properties.ContainsKey("_attachments")) { props ["_attachments"] = rev.Properties ["_attachments"]; } rev.SetProperties(props); return(true); }); context.Stack.Pop(); }
/// <summary> /// Store a collection of specified objects /// </summary> /// <param name="storableEnumerable">The objects collection to store.</param> /// <param name="forceUpdate">Update all children ignoring the <see cref="!:IStorable.IsChanged" /> flag.</param> /// <typeparam name="T">The type of the objects to store.</typeparam> public void Store <T> (IEnumerable <T> storableEnumerable, bool forceUpdate = false) where T : IStorable { List <T> newDBObjects = new List <T> (); lock (mutex) { bool success = db.RunInTransaction(() => { foreach (var t in storableEnumerable) { documentUpdated = false; try { var doc = db.GetExistingDocument(t.ID.ToString()); if (doc == null) { forceUpdate = true; newDBObjects.Add(t); } StorableNode node; ObjectChangedParser parser = new ObjectChangedParser(); parser.Parse(out node, t, Serializer.JsonSettings); if (!forceUpdate) { Update(node); } if (forceUpdate) { DocumentsSerializer.SaveObject(t, db, saveChildren: true); } if (t.ID != Info.ID && (forceUpdate || documentUpdated)) { Info.LastModified = DateTime.UtcNow; DocumentsSerializer.SaveObject(Info, db); } foreach (IStorable storable in node.OrphanChildren) { db.GetDocument(DocumentsSerializer.StringFromID(storable.ID, t.ID)).Delete(); } } catch (Exception ex) { Log.Exception(ex); return(false); } } return(true); }); if (!success) { throw new StorageException(Catalog.GetString("Error storing object from the storage")); } } foreach (var newObject in newDBObjects) { // FIXME: StorageDeletedEvent should use a collection instead of having to send one event per storable App.Current.EventsBroker.Publish(new StorageAddedEvent <T> { Object = newObject, Sender = this }); } }
void Delete(StorableNode node, Guid rootID) { Guid id = node.Storable.ID; db.GetDocument(DocumentsSerializer.StringFromID(id, rootID)).Delete(); foreach (StorableNode child in node.Children) { Delete(child, rootID); } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { IStorable storable = value as IStorable; if (context.SaveChildren && !context.Stack.Contains(value) && !context.Cache.IsCached(storable.ID)) { DocumentsSerializer.SaveObject(storable, context.DB, context); context.Cache.AddReference(storable); } writer.WriteValue(DocumentsSerializer.StringFromID(storable.ID, context.RootID)); }