Beispiel #1
0
        /// <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
                });
            }
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        /// <summary>
        /// Delete the specified collection of storable object from the database.
        /// If the object is configured to delete its children, we perform a bulk deletion of all the documents with
        /// the the storable.ID prefix, which is faster than parsing the object and it ensures that we don't leave
        /// orphaned documents in the DB
        /// </summary>
        /// <param name="storables">The objects to delete.</param>
        /// <typeparam name="T">The type of the object to delete.</typeparam>
        public void Delete <T> (IEnumerable <T> storables) where T : IStorable
        {
            lock (mutex) {
                bool success = db.RunInTransaction(() => {
                    try {
                        foreach (T storable in storables)
                        {
                            if (storable.DeleteChildren)
                            {
                                Query query = db.CreateAllDocumentsQuery();
                                // This should work, but raises an Exception in Couchbase.Lite
                                //query.StartKey = t.ID;
                                //query.EndKey = t.ID + "\uefff";

                                // In UTF-8, from all the possible values in a GUID string, '0' is the first char in the
                                // list and 'f' would be the last one
                                string sepchar     = DocumentsSerializer.ID_SEP_CHAR.ToString();
                                query.StartKey     = storable.ID + sepchar + "00000000-0000-0000-0000-000000000000";
                                query.EndKey       = storable.ID + sepchar + "ffffffff-ffff-ffff-ffff-ffffffffffff";
                                query.InclusiveEnd = true;
                                foreach (var row in query.Run())
                                {
                                    row.Document.Delete();
                                }
                            }
                            db.GetDocument(storable.ID.ToString()).Delete();
                        }
                        return(true);
                    } catch (Exception ex) {
                        Log.Exception(ex);
                        return(false);
                    }
                });
                if (success)
                {
                    Info.LastModified = DateTime.UtcNow;
                    DocumentsSerializer.SaveObject(Info, db, null, false);
                    // FIXME: StorageDeletedEvent should use a collection instead of having to send one event per storable
                    foreach (T storable in storables)
                    {
                        App.Current.EventsBroker.Publish(new StorageDeletedEvent <T> {
                            Object = storable, Sender = this
                        });
                    }
                }
                else
                {
                    throw new StorageException(Catalog.GetString("Error deleting objects from the storage"));
                }
            }
        }
Beispiel #4
0
        void Update(StorableNode node, SerializationContext context = null)
        {
            if (context == null)
            {
                context        = new SerializationContext(db, node.Storable.GetType());
                context.RootID = node.Storable.ID;
            }
            if (node.IsChanged)
            {
                documentUpdated = true;
                DocumentsSerializer.SaveObject(node.Storable, db, context, false);
            }

            /* Since we are saving single objects manually, we need to keep the stack
             * updated to avoid problems with circular references */
            context.Stack.Push(node.Storable);
            foreach (StorableNode child in node.Children)
            {
                Update(child, context);
            }
            context.Stack.Pop();
        }