/// <summary> /// Create a listener to receive changes from Firebase /// </summary> public static void ReceiveChangesFromDB() { Rootobject RootObject = new Rootobject(); try { DocumentReference docRef = firestoreDb.Collection(CollectionName).Document(DocumentName); FirestoreChangeListener listener = docRef.Listen(snapshot => { Console.WriteLine("Callback received document snapshot."); if (snapshot.Exists) { Console.WriteLine("Document data for {0} document:", snapshot.Id); var st = Newtonsoft.Json.JsonConvert.SerializeObject(snapshot.ToDictionary()); var _RootObject = Newtonsoft.Json.JsonConvert.DeserializeObject <Rootobject>(st); RhinoManagement.ProcessRemoteChanges(_RootObject); //TODO check this to detect changes } }); } catch (Exception ex) { Console.WriteLine("Error " + ex.Message); return; } }
public async void UpdatePickup(Pickups pickup, string id) { try { Google.Cloud.Firestore.DocumentReference pickupRef = fireStoreDb.Collection("pickups").Document(id); await pickupRef.SetAsync(pickup, SetOptions.Overwrite); } catch { throw; } }
public async void DeletePickup(string id) { try { Google.Cloud.Firestore.DocumentReference PickupRef = fireStoreDb.Collection("pickups").Document(id); await PickupRef.DeleteAsync(); } catch { throw; } }
/// <summary> /// Adds an operation to delete a document's data in this transaction. /// </summary> /// <param name="documentReference">The document to delete. Must not be null.</param> /// <param name="precondition">Optional precondition for deletion. May be null, in which case the deletion is unconditional.</param> public void Delete(DocumentReference documentReference, Precondition precondition = null) { // Preconditions are validated by WriteBatch. _writes.Delete(documentReference, precondition); }
/// <summary> /// Adds an operation to update a document's data in this transaction. /// </summary> /// <param name="documentReference">The document to update. Must not be null.</param> /// <param name="updates">The updates to perform on the document, keyed by the field path to update. Fields not present in this dictionary are not updated. Must not be null or empty.</param> /// <param name="precondition">Optional precondition for updating the document. May be null, which is equivalent to <see cref="Precondition.MustExist"/>.</param> public void Update(DocumentReference documentReference, IDictionary <FieldPath, object> updates, Precondition precondition = null) { // Preconditions are validated by WriteBatch. _writes.Update(documentReference, updates, precondition); }
/// <summary> /// Adds an operation to update a document's data in this transaction. /// </summary> /// <param name="documentReference">A document reference indicating the path of the document to update. Must not be null.</param> /// <param name="updates">The updates to perform on the document, keyed by the dot-separated field path to update. Fields not present in this dictionary are not updated. Must not be null or empty.</param> /// <param name="precondition">Optional precondition for updating the document. May be null, which is equivalent to <see cref="Precondition.MustExist"/>.</param> public void Update(DocumentReference documentReference, IDictionary <string, object> updates, Precondition precondition = null) { GaxPreconditions.CheckNotNull(updates, nameof(updates)); Update(documentReference, updates.ToDictionary(pair => FieldPath.FromDotSeparatedString(pair.Key), pair => pair.Value), precondition); }
/// <summary> /// Adds an operation to set a document's data in this transaction. /// </summary> /// <param name="documentReference">The document in which to set the data. Must not be null.</param> /// <param name="documentData">The data for the document. Must not be null.</param> /// <param name="options">The options to use when updating the document. May be null, which is equivalent to <see cref="SetOptions.Overwrite"/>.</param> public void Set(DocumentReference documentReference, object documentData, SetOptions options = null) { // Preconditions are validated by WriteBatch. _writes.Set(documentReference, documentData, options); }
/// <summary> /// Adds an operation to create a document in this transaction. /// </summary> /// <param name="documentReference">The document reference to create. Must not be null.</param> /// <param name="documentData">The data for the document. Must not be null.</param> public void Create(DocumentReference documentReference, object documentData) { // Preconditions are validated by WriteBatch. _writes.Create(documentReference, documentData); }
/// <summary> /// Adds an operation that sets data in a document, either replacing it completely or merging fields. /// </summary> /// <param name="documentReference">A document reference indicating the path of the document to update. Must not be null.</param> /// <param name="documentData">The data to store in the document. Must not be null.</param> /// <param name="options">The options to use when setting data in the document. May be null, which is equivalent to <see cref="SetOptions.Overwrite"/>.</param> /// <returns>This batch, for the purposes of method chaining.</returns> public WriteBatch Set(DocumentReference documentReference, object documentData, SetOptions options = null) { GaxPreconditions.CheckNotNull(documentReference, nameof(documentReference)); GaxPreconditions.CheckNotNull(documentData, nameof(documentData)); var fields = ValueSerializer.SerializeMap(documentReference.Database.SerializationContext, documentData); options = options ?? SetOptions.Overwrite; var sentinels = FindSentinels(fields); var deletes = sentinels.Where(sf => sf.IsDelete).ToList(); var nonDeletes = sentinels.Where(sf => !sf.IsDelete).ToList(); IDictionary <FieldPath, Value> updates; IReadOnlyList <FieldPath> updatePaths; if (options.Merge) { var mask = options.FieldMask; if (mask.Count == 0) { // Merge all: // - If the data is empty, we force a write // - Deletes are allowed anywhere // - All timestamps converted to transforms // - Each top-level entry becomes a FieldPath RemoveSentinels(fields, nonDeletes); // Work out the update paths after removing server timestamps but before removing deletes, // so that we correctly perform the deletes. updatePaths = ExtractDocumentMask(fields); RemoveSentinels(fields, deletes); updates = fields.ToDictionary(pair => new FieldPath(pair.Key), pair => pair.Value); } else { // Merge specific: // - Deletes must be in the mask // - Only timestamps in the mask are converted to transforms // - Apply the field mask to get the updates GaxPreconditions.CheckArgument(deletes.All(sf => mask.Contains(sf.FieldPath)), nameof(documentData), "Delete cannot appear in an unmerged field"); nonDeletes = nonDeletes.Where(sf => mask.Any(fp => fp.IsPrefixOf(sf.FieldPath))).ToList(); RemoveSentinels(fields, deletes); RemoveSentinels(fields, nonDeletes); updates = ApplyFieldMask(fields, mask); // Every field path in the mask must either refer to a now-removed sentinel, or a remaining value. // Sentinels are permitted to be in the mask in a nested fashion rather than directly, e.g. a mask of "parent" with a sentinel of "parent.child.timestamp" is fine. GaxPreconditions.CheckArgument( mask.All(p => updates.ContainsKey(p) || deletes.Any(sf => p.IsPrefixOf(sf.FieldPath)) || nonDeletes.Any(sf => p.IsPrefixOf(sf.FieldPath))), nameof(documentData), "All paths specified for merging must appear in the data."); updatePaths = mask; } } else { // Overwrite: // - No deletes allowed // - All timestamps converted to transforms // - Each top-level entry becomes a FieldPath GaxPreconditions.CheckArgument(deletes.Count == 0, nameof(documentData), "Delete cannot appear in document data when overwriting"); RemoveSentinels(fields, nonDeletes); updates = fields.ToDictionary(pair => new FieldPath(pair.Key), pair => pair.Value); updatePaths = null; } AddUpdateWrite(documentReference, ExpandObject(updates), updatePaths, precondition: null, sentinelFields: nonDeletes); return(this); }
public async void getSnapshot() { Google.Cloud.Firestore.DocumentReference docRef = db.Collection(collecName).Document(docName); DocumentSnapshot snapshot = await docRef.GetSnapshotAsync(); if (snapshot.Exists) { Console.WriteLine("Document data for {0} document:", snapshot.Id); mediaTitle.Text = "Title: " + snapshot.Id; Dictionary <string, object> media = snapshot.ToDictionary(); foreach (KeyValuePair <string, object> pair in media) { Console.WriteLine("{0}: {1}", pair.Key, pair.Value); switch (pair.Key) { case "Desc": mediaDesc.Text = "Description: " + pair.Value.ToString(); break; case "Rating": mediaRating.Text = "Rating: " + pair.Value.ToString(); break; } } } else { Console.WriteLine("Document {0} does not exist!", snapshot.Id); } //Make Review blocks Query query = db.Collection(collecName).Document(docName).Collection("reviews"); QuerySnapshot allReviewsQuerySnapshot = await query.GetSnapshotAsync(); string rating = "", desc = ""; foreach (DocumentSnapshot documentSnapshot in allReviewsQuerySnapshot.Documents) { if (documentSnapshot.Exists) { Dictionary <string, object> media = documentSnapshot.ToDictionary(); foreach (KeyValuePair <string, object> pair in media) { Console.WriteLine("{0}: {1}", pair.Key, pair.Value); switch (pair.Key) { case "desc": desc = "Description: " + pair.Value.ToString(); break; case "rating": rating = "Rating: " + pair.Value.ToString() + "/10"; break; } } Border border = new Border(); border.MinWidth = 30; border.MinHeight = 20; border.Margin = new Thickness(10); border.BorderThickness = new Thickness(5); border.CornerRadius = new CornerRadius(5); border.BorderBrush = new SolidColorBrush(Colors.Black); StackPanel panel = new StackPanel(); panel.Background = new SolidColorBrush(Colors.Black); TextBlock nameBlock = new TextBlock(); nameBlock.Background = new SolidColorBrush(Colors.Black); nameBlock.Foreground = new SolidColorBrush(Colors.White); nameBlock.Text = "Name: " + documentSnapshot.Id; nameBlock.FontSize = 15; TextBlock ratingBlock = new TextBlock(); ratingBlock.Background = new SolidColorBrush(Colors.Black); ratingBlock.Foreground = new SolidColorBrush(Colors.White); ratingBlock.Text = rating; ratingBlock.FontSize = 15; TextBlock descBlock = new TextBlock(); descBlock.Background = new SolidColorBrush(Colors.Black); descBlock.Foreground = new SolidColorBrush(Colors.White); descBlock.Text = desc; descBlock.FontSize = 15; panel.Children.Add(nameBlock); panel.Children.Add(ratingBlock); panel.Children.Add(descBlock); border.Child = panel; reviewList.Children.Add(border); } else { Console.WriteLine("Document {0} does not exist!", documentSnapshot.Id); } } }
internal IAsyncEnumerable <CollectionReference> ListCollectionsAsync(DocumentReference parent) => Client.ListCollectionIdsAsync(parent?.Path ?? RootPath) .Select(id => new CollectionReference(this, parent, id));
/// <summary> /// Constructs a new context. /// </summary> /// <param name="reference">The document being deserialized. Must not be null.</param> internal DeserializationContext(DocumentReference reference) { DocumentReference = GaxPreconditions.CheckNotNull(reference, nameof(reference)); }
public async Task <WatchResponseResult> HandleResponseAsync(ListenResponse response, CancellationToken cancellationToken) { switch (response.ResponseTypeCase) { case ListenResponse.ResponseTypeOneofCase.TargetChange: TargetChange change = response.TargetChange; bool noTargetIds = change.TargetIds.Count == 0; switch (change.TargetChangeType) { case NoChange: if (noTargetIds && change.ReadTime != null && _current) { // This means everything is up-to-date, so emit the current set of docs as a snapshot, // if there were changes. await PushSnapshotAsync(Timestamp.FromProto(change.ReadTime), change.ResumeToken, cancellationToken).ConfigureAwait(false); } break; case Add: GaxPreconditions.CheckState(!noTargetIds && WatchStream.WatchTargetId == change.TargetIds[0], "Target ID must be 0x{0:x}", WatchStream.WatchTargetId); break; case Remove: GaxPreconditions.CheckState(!noTargetIds && WatchStream.WatchTargetId == change.TargetIds[0], "Target ID must be 0x{0:x}", WatchStream.WatchTargetId); // This may not be the right kind of exception to throw, but whatever we throw should be a permanent error. This is a reasonable starting point. throw new InvalidOperationException("Server removed watch target"); case Current: _current = true; break; case Reset: ResetDocs(); return(WatchResponseResult.Continue); default: throw new InvalidOperationException($"Encountered invalid target change type: {change.Cause.Message}"); } bool healthy = change.ResumeToken != null && (change.TargetIds.Count == 0 || change.TargetIds.Contains(WatchStream.WatchTargetId)); // Possibly tell the watch stream that it's now healthy (so reset backoff), or just continue. return(healthy ? WatchResponseResult.StreamHealthy : WatchResponseResult.Continue); case ListenResponse.ResponseTypeOneofCase.DocumentChange: // No other targetIds can show up here, but we still need to see if the targetId was in the // added list or removed list. var changed = response.DocumentChange.TargetIds.Contains(WatchStream.WatchTargetId); var removed = response.DocumentChange.RemovedTargetIds.Contains(WatchStream.WatchTargetId); Document document = response.DocumentChange.Document; DocumentReference docRef = CreateDocumentReference(document.Name); if (changed && removed) { throw new InvalidOperationException("Server error: document was both changed and removed"); } if (!changed && !removed) { // This is probably an error in the server, but we can follow protocol by just ignoring this response. return(WatchResponseResult.Continue); } _changeMap[docRef] = changed ? document : null; return(WatchResponseResult.Continue); case ListenResponse.ResponseTypeOneofCase.DocumentDelete: _changeMap[CreateDocumentReference(response.DocumentDelete.Document)] = null; return(WatchResponseResult.Continue); case ListenResponse.ResponseTypeOneofCase.DocumentRemove: _changeMap[CreateDocumentReference(response.DocumentRemove.Document)] = null; return(WatchResponseResult.Continue); case ListenResponse.ResponseTypeOneofCase.Filter: // TODO: Do we really want to create the change set itself, rather than just count? It seems a bit wasteful. ChangeSet changeSet = ExtractChanges(default); int currentSize = _documentSet.Count + changeSet.Adds.Count - changeSet.Deletes.Count; // Reset the stream if we don't have the right number of documents. if (response.Filter.Count != currentSize) { ResetDocs(); return(WatchResponseResult.ResetStream); } return(WatchResponseResult.Continue); default: throw new InvalidOperationException($"Encountered invalid listen response type: {response.ResponseTypeCase}"); } }
internal bool TryGetDocument(DocumentReference docRef, out DocumentSnapshot document) => _keyIndex.TryGetValue(docRef, out document);
internal bool Contains(DocumentReference docRef) => _keyIndex.ContainsKey(docRef);