/// <summary> /// First use HEAD to see if it has indeed changed. /// </summary> /// <param name="document">Document to fill.</param> public void FetchDocumentIfChanged(ICouchDocument document) { if (HasDocumentChanged(document)) { ReadDocument(document); } }
/// <summary> /// Automatically reconcile the database copy with the target instance. This method /// uses reflection to perform the reconcilliation, and as such won't perform as well /// as other version, but is available for low-occurance scenarios /// </summary> /// <param name="databaseCopy"></param> protected void AutoReconcile(ICouchDocument databaseCopy) { var properties = GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); var fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); foreach (var field in fields) { // if we haven't changed the field, if (EqualFields(field.GetValue(sourceData), field.GetValue(this))) { field.SetValue(this, field.GetValue(databaseCopy)); } } foreach (var prop in properties) { if (!prop.CanWrite || prop.GetIndexParameters().Length > 0) { continue; } else if (EqualFields(prop.GetValue(sourceData, null), prop.GetValue(this, null))) { prop.SetValue(this, prop.GetValue(databaseCopy, null), null); } } // this is non-negotiable Rev = databaseCopy.Rev; }
public void ShouldStoreGetAndDeleteAttachment() { var doc = new CouchJsonDocument("{\"CPU\": \"Intel\"}"); ICouchDocument cd = db.CreateDocument(doc); var attachmentName = "someAttachment.txt"; Assert.That(db.HasAttachment(cd, attachmentName), Is.False); db.WriteAttachment(cd, attachmentName, "jabbadabba", "text/plain"); Assert.That(db.HasAttachment(cd, attachmentName), Is.True); using (var response = db.ReadAttachment(cd, attachmentName)) { using (var reader = new StreamReader(response.GetResponseStream())) { Assert.That(reader.ReadToEnd(), Is.EqualTo("jabbadabba")); } } db.WriteAttachment(cd, attachmentName, "jabbadabba-doo", "text/plain"); Assert.That(db.HasAttachment(cd, attachmentName), Is.True); using (var response = db.ReadAttachment(cd, attachmentName)) { using (var reader = new StreamReader(response.GetResponseStream())) { Assert.That(reader.ReadToEnd(), Is.EqualTo("jabbadabba-doo")); } } db.DeleteAttachment(cd, attachmentName); Assert.That(db.HasAttachment(cd, attachmentName), Is.False); }
public ICouchDocument DeleteAttachment(ICouchDocument document, string attachmentName) { JObject result = Request(document.Id + "/" + attachmentName).Query("?rev=" + document.Rev).Delete().Check("Failed to delete attachment").Result(); document.Id = result["id"].Value <string>(); // Not really neeed document.Rev = result["rev"].Value <string>(); return(document); }
public void ShouldSaveDocumentWithId() { var doc = new CouchJsonDocument("{\"_id\":\"123\", \"CPU\": \"Intel\"}"); ICouchDocument cd = db.SaveDocument(doc); Assert.That(db.CountDocuments(), Is.EqualTo(1)); Assert.That(cd.Id, Is.Not.Null); Assert.That(cd.Rev, Is.Not.Null); }
public void ShouldCreateDocument() { var doc = new CouchJsonDocument("{\"CPU\": \"Intel\"}"); ICouchDocument cd = db.CreateDocument(doc); Assert.That(db.CountDocuments(), Is.EqualTo(1)); Assert.That(cd.Id, Is.Not.Null); Assert.That(cd.Rev, Is.Not.Null); }
/// <summary> /// Read a CouchDocument or ICouchDocument, this relies on the document to obviously have an id. /// We also check the revision so that we can avoid parsing JSON if the document is unchanged. /// </summary> /// <param name="document">Document to fill.</param> public void ReadDocumentIfChanged(ICouchDocument document) { JObject result = Request(document.Id).Etag(document.Rev).Parse(); if (result == null) { return; } document.ReadJson(result); }
/// <summary> /// Called by the runtime when a conflict is detected during save. The supplied parameter /// is the database copy of the document being saved. /// </summary> /// <param name="databaseCopy"></param> public virtual void Reconcile(ICouchDocument databaseCopy) { if (ReconcileBy == ReconcileStrategy.AutoMergeFields) { AutoReconcile(databaseCopy); return; } Rev = databaseCopy.Rev; }
public override bool Equals(object obj) { ICouchDocument o = obj as ICouchDocument; if (o == null) { return(false); } return(o.Id == Id && o.Rev == Rev); }
public static void WriteIdAndRev(ICouchDocument doc, JsonWriter writer) { if (doc.Id != null) { writer.WritePropertyName("_id"); writer.WriteValue(doc.Id); } if (doc.Rev != null) { writer.WritePropertyName("_rev"); writer.WriteValue(doc.Rev); } }
/// <summary> /// Create a given ICouchDocument in CouchDB. Uses POST and CouchDB will allocate a new id and overwrite any existing id. /// </summary> /// <param name="document">Document to store.</param> /// <returns>Document with Id and Rev set.</returns> /// <remarks>POST which may be problematic in some environments.</remarks> public ICouchDocument CreateDocument(ICouchDocument document) { try { JObject result = Request().Data(CouchDocument.WriteJson(document)).PostJson().Check("Failed to create document").Result(); document.Id = result["id"].Value <string>(); document.Rev = result["rev"].Value <string>(); return(document); } catch (WebException e) { throw CouchException.Create("Failed to create document", e); } }
public static void ReadIdAndRev(ICouchDocument doc, JsonReader reader) { reader.Read(); if (reader.TokenType == JsonToken.PropertyName && (reader.Value as string == "_id")) { reader.Read(); doc.Id = reader.Value as string; } reader.Read(); if (reader.TokenType == JsonToken.PropertyName && (reader.Value as string == "_rev")) { reader.Read(); doc.Rev = reader.Value as string; } }
/// <summary> /// Write a CouchDocument or ICouchDocument, it may already exist in db and will then be overwritten. /// </summary> /// <param name="document">Couch document</param> /// <param name="batch">True if we don't want to wait for flush (commit).</param> /// <returns>Couch Document with new Rev set.</returns> /// <remarks>This relies on the document to already have an id.</remarks> public ICouchDocument WriteDocument(ICouchDocument document, bool batch) { if (document.Id == null) { throw CouchException.Create( "Failed to write document using PUT because it lacks an id, use CreateDocument instead to let CouchDB generate an id"); } JObject result = Request(document.Id).Query(batch ? "?batch=ok" : null).Data(CouchDocument.WriteJson(document)).Put().Check("Failed to write document").Result(); document.Id = result["id"].Value <string>(); // Not really needed document.Rev = result["rev"].Value <string>(); return(document); }
/// <summary> /// Writes the attachment. /// </summary> /// <param name="document">The document.</param> /// <param name="attachmentName">Name of the attachment.</param> /// <param name="attachmentData">The attachment data.</param> /// <param name="mimeType">Type of the MIME.</param> /// <returns>The document.</returns> /// <remarks>This relies on the document to already have an id.</remarks> public ICouchDocument WriteAttachment(ICouchDocument document, string attachmentName, Stream attachmentData, string mimeType) { if (document.Id == null) { throw CouchException.Create( "Failed to add attachment to document using PUT because it lacks an id"); } JObject result = Request(document.Id + "/" + attachmentName).Query("?rev=" + document.Rev).Data(attachmentData).MimeType(mimeType).Put().Check("Failed to write attachment") .Result(); document.Id = result["id"].Value <string>(); // Not really neeed document.Rev = result["rev"].Value <string>(); return(document); }
/// <summary> /// This is a convenience method that creates or writes a ICouchDocument depending on if /// it has an id or not. If it does not have an id we create the document and let CouchDB allocate /// an id. If it has an id we use WriteDocument which will overwrite the existing document in CouchDB. /// </summary> /// <param name="document">ICouchDocument</param> /// <returns>ICouchDocument with new Rev set.</returns> public ICouchDocument SaveDocument(ICouchDocument document) { var reconcilingDoc = document as IReconcilingDocument; ICouchDocument savedDoc; try { savedDoc = document.Id == null? CreateDocument(document) : WriteDocument(document); } catch (CouchConflictException) { if (reconcilingDoc == null) { throw; } // can't handle a brand-new document if (String.IsNullOrEmpty(reconcilingDoc.Rev)) { throw; } switch (reconcilingDoc.ReconcileBy) { case ReconcileStrategy.None: throw; default: reconcilingDoc.Reconcile(reconcilingDoc.GetDatabaseCopy(this)); SaveDocument(reconcilingDoc); break; } savedDoc = reconcilingDoc; } if (reconcilingDoc != null) { reconcilingDoc.SaveCommited(); } return(savedDoc); }
public void Should_Trigger_Replication_using_replicator_db() { CouchDatabase replDb = client.GetDatabase("_replicator"); ICouchDocument existingDoc = replDb.GetDocument <JDocument>("C"); if (existingDoc != null) { replDb.DeleteDocument(existingDoc); } CouchReplicationDocument doc = replDb.CreateDocument( new CouchReplicationDocument { Id = "C", Source = baseDatabase, Target = String.Format("http://{0}:5984/{1}", couchdbHostName, replicateDatabase), Continuous = true, UserContext = new UserContext { Name = "bob", Roles = new[] { "role1", "role2" } } }); //Sleep two second to ensure the replicationid is set by couchdb System.Threading.Thread.Sleep(2000); CouchReplicationDocument doc2 = replDb.GetDocument <CouchReplicationDocument>("C"); Assert.IsNotEmpty(doc2.ReplicationId); Assert.IsNotEmpty(doc2.ReplicationState); Assert.IsTrue(doc2.Continuous); Assert.IsTrue(doc2.ReplicationStateTime.HasValue); Assert.IsNotNull(doc2.UserContext); Assert.AreEqual("bob", doc2.UserContext.Name); Assert.AreEqual(2, doc2.UserContext.Roles.Length); Assert.AreEqual("role1", doc2.UserContext.Roles[0]); Assert.AreEqual("role2", doc2.UserContext.Roles[1]); replDb.DeleteDocument(doc2); }
/// <summary> /// <para>Deletes an attachment. The most recent revision will be used. /// </para> /// <para>(This method is asynchronous.)</para> /// </summary> /// <param name="doc">ICouchDocument object.</param> /// <param name="fileName">Filename of the attachment.</param> /// <param name="result"></param> /// <returns></returns> public Result<JObject> DeleteAttachment( ICouchDocument doc, string fileName, Result<JObject> result) { if (doc == null) throw new ArgumentNullException("doc"); DeleteAttachment(doc.Id, doc.Rev, fileName, result).WhenDone( result.Return, result.Throw ); return result; }
/// <summary> /// Deletes an attachment. The most recent revision will be used. /// </summary> /// <param name="doc">ICouchDocument object.</param> /// <param name="fileName">Filename of the attachment.</param> /// <returns></returns> public JObject DeleteAttachment(ICouchDocument doc, string fileName) { return DeleteAttachment(doc, fileName, new Result<JObject>()).Wait(); }
/// <summary> /// <para>Retrieves an attachment. The most recent revision will be used. /// </para> /// <para>(This method is asynchronous.)</para> /// </summary> /// <param name="doc">ICouchDocument object.</param> /// <param name="fileName">Filename of the attachment.</param> /// <param name="result"></param> /// <returns></returns> public Result<Stream> GetAttachment( ICouchDocument doc, string fileName, Result<Stream> result) { if (doc == null) throw new ArgumentNullException("doc"); return GetAttachment(doc.Id, doc.Rev, fileName, result); }
/// <summary> /// Copies the specified source document to the destination document, replacing it. /// </summary> /// <param name="sourceDocument">The source document.</param> /// <param name="destinationDocument">The destination document.</param> /// <remarks>This method does not update the destinationDocument object.</remarks> public void Copy(ICouchDocument sourceDocument, ICouchDocument destinationDocument) { Copy(sourceDocument.Id, destinationDocument.Id, destinationDocument.Rev); }
public bool HasDocumentChanged(ICouchDocument document) { return(HasDocumentChanged(document.Id, document.Rev)); }
public bool HasAttachment(ICouchDocument document, string attachmentName) { return(HasAttachment(document.Id, attachmentName)); }
/// <summary> /// Retrieves an attachment. The most recent revision will be used. /// </summary> /// <param name="doc">ICouchDocument object.</param> /// <param name="fileName">Filename of the attachment.</param> /// <returns></returns> public Stream GetAttachment(ICouchDocument doc, string fileName) { return GetAttachment(doc, fileName, new Result<Stream>()).Wait(); }
public void DeleteDocument(ICouchDocument document) { DeleteDocument(document.Id, document.Rev); }
public static void ReadIdAndRev(ICouchDocument doc, JObject obj) { doc.Id = obj["_id"].Value <string>(); doc.Rev = obj["_rev"].Value <string>(); }
WriteDocument(ICouchDocument document) { return(WriteDocument(document, false)); }
/// <summary> /// Adds an attachment from a specified path. The most recent revision will /// be used. Warning: if you need to prevent document update conflicts, then /// please use the method that specifies the revision. /// </summary> /// <param name="doc">ICouchDocument object.</param> /// <param name="filePath">Path of the attachment to be added.</param> /// <returns></returns> public JObject AddAttachment(ICouchDocument doc, string filePath) { return AddAttachment(doc, filePath, new Result<JObject>()).Wait(); }
static void Main() { //This is real username and password and must work with them CouchServer server = new CouchServer("testuser.cloudant.com", 5984, "testuser", "testpassword"); ICouchDatabase database = server.GetDatabase("dictionary"); bool isWorking = true; ICouchDocument doc = database.GetDocument("game"); while (isWorking) { Console.WriteLine("For add new word press : 1"); Console.WriteLine("For finding a translation for given word press 2"); Console.WriteLine("For list all words and their translations press 3"); Console.WriteLine("For exit press 4"); string command = Console.ReadLine(); switch (command) { case "1": { Console.WriteLine("Enter word"); string word = Console.ReadLine(); Console.WriteLine("Enter translation"); string translation = Console.ReadLine(); CreateWord(word, translation, database); } break; case "2": { Console.WriteLine("Enter word"); string word = Console.ReadLine(); GetWordTranslation(word, database); } break; case "3": { ListAllLords(database); } break; case "4": { isWorking = false; } break; default: { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Unknown Command"); Console.ResetColor(); } break; } } }
public bool HasDocument(ICouchDocument document) { return(HasDocument(document.Id)); }
/// <summary> /// Read a ICouchDocument with an id even if it has not changed revision. /// </summary> /// <param name="document">Document to fill.</param> public void ReadDocument(ICouchDocument document) { document.ReadJson(ReadDocument(document.Id)); }
/// <summary> /// Add an attachment to an existing ICouchDocument, it may already exist in db and will then be overwritten. /// </summary> /// <param name="document">Couch document</param> /// <param name="attachmentName">Name of the attachment.</param> /// <param name="attachmentData">The attachment data.</param> /// <param name="mimeType">The MIME type for the attachment.</param> /// <returns>The document.</returns> /// <remarks>This relies on the document to already have an id.</remarks> public ICouchDocument WriteAttachment(ICouchDocument document, string attachmentName, string attachmentData, string mimeType) { var byteData = Encoding.UTF8.GetBytes(attachmentData); return(WriteAttachment(document, attachmentName, byteData, mimeType)); }
public static void ReadIdAndRev(ICouchDocument doc, JObject obj) { doc.Id = obj["_id"].Value<string>(); doc.Rev = obj["_rev"].Value<string>(); }
/// <summary> /// Read the attachment for an ICouchDocument. /// </summary> /// <param name="document">Document to read.</param> /// <param name="attachmentName">Name of the attachment.</param> /// <returns></returns> public WebResponse ReadAttachment(ICouchDocument document, string attachmentName) { return(ReadAttachment(document.Id, attachmentName)); }
/// <summary> /// Automatically reconcile the database copy with the target instance. This method /// uses reflection to perform the reconcilliation, and as such won't perform as well /// as other version, but is available for low-occurance scenarios /// </summary> /// <param name="databaseCopy"></param> protected void AutoReconcile(ICouchDocument databaseCopy) { var properties = GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); var fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); foreach (var field in fields) // if we haven't changed the field, if (EqualFields(field.GetValue(sourceData), field.GetValue(this))) field.SetValue(this, field.GetValue(databaseCopy)); foreach (var prop in properties) if (!prop.CanWrite || prop.GetIndexParameters().Length > 0) continue; else if (EqualFields(prop.GetValue(sourceData, null), prop.GetValue(this, null))) prop.SetValue(this, prop.GetValue(databaseCopy, null), null); // this is non-negotiable Rev = databaseCopy.Rev; }
/// <summary> /// <para>Adds an attachment from a specified path. The most recent revision /// will be used. Warning: if you need to prevent document update conflicts, /// then please use the method that specifies the revision.</para> /// <para>(This method is asynchronous.)</para> /// </summary> /// <param name="doc">ICouchDocument object.</param> /// <param name="filePath">Path of the attachment to be added.</param> /// <param name="result"></param> /// <returns></returns> public Result<JObject> AddAttachment( ICouchDocument doc, string filePath, Result<JObject> result) { if (doc == null) throw new ArgumentNullException("doc"); if (String.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath"); if (!File.Exists(filePath)) throw new FileNotFoundException("File not found", filePath); return AddAttachment(doc.Id, doc.Rev, File.Open(filePath, FileMode.Open), -1, Path.GetFileName(filePath), result); }