예제 #1
0
 /// <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);
     }
 }
예제 #2
0
        /// <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;
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        /// <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;
        }
예제 #9
0
        public override bool Equals(object obj)
        {
            ICouchDocument o = obj as ICouchDocument;

            if (o == null)
            {
                return(false);
            }

            return(o.Id == Id && o.Rev == Rev);
        }
예제 #10
0
 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);
     }
 }
예제 #11
0
 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);
     }
 }
예제 #12
0
 /// <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);
     }
 }
예제 #13
0
 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;
     }
 }
예제 #14
0
        /// <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);
        }
예제 #15
0
 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;
     }
 }
예제 #16
0
        /// <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);
        }
예제 #17
0
        /// <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);
        }
예제 #18
0
        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);
        }
예제 #22
0
 /// <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);
 }
예제 #23
0
 public bool HasDocumentChanged(ICouchDocument document)
 {
     return(HasDocumentChanged(document.Id, document.Rev));
 }
예제 #24
0
 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();
 }
예제 #26
0
 public void DeleteDocument(ICouchDocument document)
 {
     DeleteDocument(document.Id, document.Rev);
 }
예제 #27
0
 public static void ReadIdAndRev(ICouchDocument doc, JObject obj)
 {
     doc.Id  = obj["_id"].Value <string>();
     doc.Rev = obj["_rev"].Value <string>();
 }
예제 #28
0
 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();
 }
예제 #30
0
        /// <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;
        }
예제 #31
0
        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;
                }
            }
        }
예제 #32
0
 public bool HasDocument(ICouchDocument document)
 {
     return(HasDocument(document.Id));
 }
예제 #33
0
 /// <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));
 }
예제 #34
0
        /// <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));
        }
예제 #35
0
 public static void ReadIdAndRev(ICouchDocument doc, JObject obj)
 {
     doc.Id = obj["_id"].Value<string>();
     doc.Rev = obj["_rev"].Value<string>();
 }
예제 #36
0
 /// <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));
 }
예제 #37
0
        /// <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);
        }