<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.abdullin.com/~d/styles/itemcontent.css"?><!--Generated by Squarespace Site Server v5.11.81 (http://www.squarespace.com/) on Mon, 06 Feb 2012 11:40:31 GMT--><feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><title type="text">Rinat Abdullin on CouchDB</title><subtitle type="html">Articles and journal posts about using CouchDB in .NET applications.</subtitle><id>http://abdullin.com/journal/</id><link rel="alternate" type="application/xhtml+xml" href="http://abdullin.com/journal/" /><updated>2012-02-06T11:16:21Z</updated><generator uri="http://www.squarespace.com/" version="Squarespace Site Server v5.11.81 (http://www.squarespace.com/)">Squarespace</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.abdullin.com/couchdb" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="couchdb" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry><title>10 Steps To Become Better .NET Developer</title><category term="Azure" /><category term="CC.NET" /><category term="CQRS" /><category term="Castle" /><category term="Cloud Computing" /><category term="CouchDB" /><category term="DDD" /><category term="IoC" /><category term="Linux" /><category term="Mono" /><category term="NHibernate" /><category term="NServiceBus" /><category term="ORM" /><category term="autofac" /><category term="xLim" /><id>http://abdullin.com/journal/2010/11/19/10-steps-to-become-better-net-developer.html</id><link rel="alternate" type="text/html" href="http://abdullin.com/journal/2010/11/19/10-steps-to-become-better-net-developer.html" /><author><name>Rinat Abdullin</name></author><published>2010-11-19T10:20:17Z</published><updated>2010-11-19T10:20:17Z</updated><content type="html" xml:lang="en-US">&lt;p&gt;Here's a list of things you might want to learn about in order to become a better .NET developer. Better developers are eligible to &lt;strong&gt;higher paychecks&lt;/strong&gt;, &lt;strong&gt;exciting projects&lt;/strong&gt; and &lt;strong&gt;more freedom&lt;/strong&gt; in their lifestyles.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learn &lt;a href="http://abdullin.com/wiki/unit-testing.html"&gt;Unit Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Get familiar with distributed &lt;a href="http://abdullin.com/wiki/version-control-system-vcs.html" target="_blank" class="offsite-link-inline"&gt;Version Control Systems&lt;/a&gt;: &lt;a href="http://git-scm.com/" target="_blank" class="offsite-link-inline"&gt;Git&lt;/a&gt; or &lt;a href="http://mercurial.selenic.com/" target="_blank" class="offsite-link-inline"&gt;Mercurial&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Learn about &lt;a href="http://abdullin.com/wiki/inversion-of-control-ioc.html" target="_blank" class="offsite-link-inline"&gt;IoC Containers&lt;/a&gt;: &lt;a href="http://abdullin.com/autofac/" target="_blank" class="offsite-link-inline"&gt;Autofac&lt;/a&gt;, &lt;a href="http://www.castleproject.org/container/index.html" target="_blank" class="offsite-link-inline"&gt;Windsor Container&lt;/a&gt; and &lt;a href="http://structuremap.net/structuremap/index.html" target="_blank" class="offsite-link-inline"&gt;StructureMap&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/journal/2010/11/23/open-source-is-so-much-better-than-university.html"&gt;Contribute to Open Source Projects&lt;/a&gt; of your choice.&lt;/li&gt;
&lt;li&gt;Learn about &lt;a href="http://abdullin.com/wiki/continuous-integration.html"&gt;Continuous Integration&lt;/a&gt; and try setting up &lt;a href="http://www.jetbrains.com/teamcity/" target="_blank" class="offsite-link-inline"&gt;TeamCity&lt;/a&gt;, &lt;a href="https://hudson.dev.java.net/" target="_blank" class="offsite-link-inline"&gt;Hudson&lt;/a&gt; or &lt;a href="http://confluence.public.thoughtworks.org/display/CCNET/Welcome+to+CruiseControl.NET" target="_blank" class="offsite-link-inline"&gt;CruiseControl.NET&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Learn about &lt;a href="http://nhforge.org/Default.aspx" target="_blank" class="offsite-link-inline"&gt;NHibernate&lt;/a&gt; Object Relational Mapper, but be prepared to outgrow it for NoSQL persistence like &lt;a href="http://couchdb.apache.org/" target="_blank" class="offsite-link-inline"&gt;CouchDB&lt;/a&gt;, &lt;a href="http://www.mongodb.org/" target="_blank" class="offsite-link-inline"&gt;MongoDB&lt;/a&gt; or &lt;a href="http://ravendb.net/" target="_blank" class="offsite-link-inline"&gt;RavenDB&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Check out the buzz about &lt;a href="http://abdullin.com/cloud-computing/" target="_blank" class="offsite-link-inline"&gt;cloud computing&lt;/a&gt;, try &lt;a href="http://www.microsoft.com/windowsazure/" target="_blank" class="offsite-link-inline"&gt;Windows Azure Platform&lt;/a&gt; and also give a shot to running your .NET App with &lt;a href="http://www.mycloudideas.com/2010/get-net-cloud-server-on-ubuntu-linux-vm-with-mono" target="_blank" class="offsite-link-inline"&gt;Mono on Linux&lt;/a&gt; (&lt;a href="http://abdullin.com/journal/2010/11/25/free-cloud-computing-offers.html"&gt;some free offers&lt;/a&gt; to try).&lt;/li&gt;
&lt;li&gt;Familiarize yourself with messaging architectures and try &lt;a href="http://www.nservicebus.com/" target="_blank" class="offsite-link-inline"&gt;NServiceBus&lt;/a&gt;, &lt;a href="http://code.google.com/p/masstransit/" target="_blank" class="offsite-link-inline"&gt;MassTransit&lt;/a&gt; or &lt;a href="https://github.com/ayende/rhino-queues" target="_blank" class="offsite-link-inline"&gt;RhinoQueues&lt;/a&gt;; then learn about alternative to MSMQ - &lt;a href="http://www.amqp.org/confluence/display/AMQP/Advanced+Message+Queuing+Protocol" target="_blank" class="offsite-link-inline"&gt;AMQP&lt;/a&gt; and &lt;a href="http://www.rabbitmq.com/" target="_blank" class="offsite-link-inline"&gt;RabbitMQ&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Read &lt;a href="http://www.amazon.com/gp/product/0321125215?ie=UTF8&amp;amp;tag=abdullin-20" target="_blank" class="offsite-link-inline"&gt;Domain-Driven Design&lt;/a&gt; and apply it in your projects.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/cqrs/"&gt;Get Started with CQRS Architectures&lt;/a&gt; and practice it in a learning project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you can see, the list is not endless. There are just ten distinct topics structured in the recommended order of learning and practicing. Diligently walking through them is certain to get you way above the level of Senior Developer, opening a whole set of opportunities all around the world.&lt;/p&gt;

&lt;p&gt;And if you happened to learn, understand and master all these steps and still don't have interesting job or project offer - &lt;a href="http://abdullin.com/contact/"&gt;drop me an email&lt;/a&gt;; I might get you in touch with folks &lt;strong&gt;desperately looking for developers with this set of skills&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=kK7ieEmxgNw:8cUMC5jYHKQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?i=kK7ieEmxgNw:8cUMC5jYHKQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=kK7ieEmxgNw:8cUMC5jYHKQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?i=kK7ieEmxgNw:8cUMC5jYHKQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=kK7ieEmxgNw:8cUMC5jYHKQ:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=kK7ieEmxgNw:8cUMC5jYHKQ:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry><entry><title>CouchDB - Document Persistence Powered by CQRS</title><category term="CQRS" /><category term="Cloud Computing" /><category term="CouchDB" /><category term="Theory" /><category term="thoughts" /><id>http://abdullin.com/journal/2010/4/8/couchdb-document-persistence-powered-by-cqrs.html</id><link rel="alternate" type="text/html" href="http://abdullin.com/journal/2010/4/8/couchdb-document-persistence-powered-by-cqrs.html" /><author><name>Rinat Abdullin</name></author><published>2010-04-08T10:09:46Z</published><updated>2010-04-08T10:09:46Z</updated><content type="html" xml:lang="en-US">&lt;p&gt;&lt;em&gt;I've been asked about my opinion on the CouchDb (MongoDb) multiple times. Here's my current analysis and opinion.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As any .NET developer I've tried working with the document-oriented databases. In my case the introduction started with the CouchDB. There was some &lt;a href="http://abdullin.com/ncouch"&gt;research and development&lt;/a&gt; including the &lt;a href="http://code.google.com/p/ncouch/" target="_blank" class="offsite-link-inline"&gt;NCouch project.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CouchDB is a database famous for its distributed nature, great read performance and schema-less nature of the documents&lt;/strong&gt; (&lt;a href="http://abdullin.com/journal/2009/7/21/couchdb-in-the-cloud-cheap-and-flexible-persistence-for-net.html"&gt;CouchDb overview and introduction for .NET&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;These nice features come right of the box, when you deploy CouchDB. And they are actually available out there for you because CouchDB partially implements &lt;a href="http://abdullin.com/cqrs"&gt;Command-Query Responsibility Segregation principles&lt;/a&gt;. These benefits are inherent to the CQRS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free schema&lt;/li&gt;
&lt;li&gt;High read performance &lt;/li&gt;
&lt;li&gt;Replication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Indeed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free schema in CouchDb - persistence ignorance in the CQRS.&lt;/li&gt;
&lt;li&gt;Multiple view engines in CouchDb - multiple subscribed event denormalizers in the CQRS.&lt;/li&gt;
&lt;li&gt;High read performance of CouchDb views - high read performance against denormalized query tables.&lt;/li&gt;
&lt;li&gt;Auto replication in CouchDb - Publish/Subscribe in CQRS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From this standpoint &lt;strong&gt;CouchDb is an extremely nice base for building lightweight and high-performance document-oriented web applications&lt;/strong&gt;, since you get all the performance features packed nicely with the REST API, JSON and ability to write view engines in multiple languages.&lt;/p&gt;

&lt;p&gt;CouchDb might work for you even if you are not working on the web. If your solution is heavily into the domain of documents and unstructured data, then CQRS has chances of fitting nicely there. &lt;/p&gt;

&lt;p&gt;However, if your domain deals with the &lt;strong&gt;business processes&lt;/strong&gt;, where &lt;strong&gt;changes could be more important than just the data&lt;/strong&gt;, then it is better to implement a CQRS-based solution yourself. You'd get similar performance and scalability benefits as CouchDb.&lt;/p&gt;

&lt;p&gt;Let's take a moment to think about the logical &lt;strong&gt;differences between the data (state) and changes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State&lt;/strong&gt; is a version of a document, static snapshot or immutable representation of something. Change is a step in the process, that describes "&lt;em&gt;how did we get to the version 2 from version 1&lt;/em&gt;" or "&lt;em&gt;what happened between the lines&lt;/em&gt;". As such, change captures much more contextual information about the process, than the mere difference between the two versions. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In business contextual information is the king.&lt;/strong&gt; It is so important, that changes are often treated like full-class citizens. Sometimes you can meet them under the names of events, commands or workflows. We even got persistence pattern that is based on events, rather than on the state - Event Sourcing.&lt;/p&gt;

&lt;p&gt;Given all that, &lt;strong&gt;my impression about CouchDB&lt;/strong&gt; is: CouchDB is a young document-oriented database that leans towards the web applications and is based on the CQRS principles. The latter gives it nice performance, distribution and scalability.&lt;/p&gt;

&lt;p&gt;Unfortunately, as a .NET developer focused on the distributed enterprise applications targeting business scenarios, I don't have a lot of use cases for such an interesting tool.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This article concludes &lt;a href="http://abdullin.com/ncouch"&gt;my study of the CouchDB&lt;/a&gt;, for now. It also represents implementation study for the &lt;a href="http://abdullin.com/cqrs"&gt;CQRS research&lt;/a&gt;, which is a part of &lt;a href="http://abdullin.com/xlim/"&gt;xLim 4 body of knowledge&lt;/a&gt;.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=Zpt0cuiuXxs:MejMDiapWa8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?i=Zpt0cuiuXxs:MejMDiapWa8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=Zpt0cuiuXxs:MejMDiapWa8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?i=Zpt0cuiuXxs:MejMDiapWa8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=Zpt0cuiuXxs:MejMDiapWa8:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=Zpt0cuiuXxs:MejMDiapWa8:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry><entry><title>CouchDB in the Cloud - Persisting From .NET Code</title><category term="Articles" /><category term="Cloud Computing" /><category term="CouchDB" /><id>http://abdullin.com/journal/2009/7/24/couchdb-in-the-cloud-persisting-from-net-code.html</id><link rel="alternate" type="text/html" href="http://abdullin.com/journal/2009/7/24/couchdb-in-the-cloud-persisting-from-net-code.html" /><author><name>Rinat Abdullin</name></author><published>2009-07-24T10:43:40Z</published><updated>2009-07-24T10:43:40Z</updated><content type="html" xml:lang="en-US">&lt;p&gt;This article about CouchDB is a research that continues topics of &lt;a href="http://abdullin.com/xlim/"&gt;xLim&lt;/a&gt; and &lt;a href="http://abdullin.com/cloud-computing-in-net/"&gt;Cloud Computing in .NET&lt;/a&gt; series. &lt;/p&gt;

&lt;p&gt;In the previous article we've talked about &lt;a href="http://abdullin.com/journal/2009/7/21/couchdb-in-the-cloud-cheap-and-flexible-persistence-for-net.html"&gt;deploying CouchDB servers in the cloud and locally&lt;/a&gt;. Now it is time to outline a simple .NET adapter for communicating with these servers.&lt;/p&gt;

&lt;p&gt;In order to talk to CouchDB we need a few pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON serializer - &lt;em&gt;ISerializer&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Service for getting and posting REST commands - &lt;em&gt;IRestClient&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Actual implementation of CouchDB client - &lt;em&gt;CouchServer&lt;/em&gt; and &lt;em&gt;CouchDatabase&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These pieces might fall together in an extremely simple (yet extensible) fashion:&lt;/p&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/07/2009-07-21_simplified_couch_db_for_net.png" alt="Simplified CouchDB wrapper for .NET"/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Let's go with the most simple implementation that will let us execute code like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Test]
public void RoundTrip_Class()
{
    // connect to the database
    var database = CouchFactory.ConnectToDatabase(DBUrl);

    // create new document objecy
    var user = new SampleUser
    {
        Name = "user@unknown.com",
        Tags = new[] { "User", "Can have attachments"}
    };
    // save document, specifying the identifier
    var revision = database.SaveDocument(user, u =&amp;gt; u.Name);
    Assert.AreEqual(user.Name, revision.Id);

    // retrieve the document
    var retrievedUser = database.GetDocument&amp;lt;SampleUser&amp;gt;(user.Name);
    Assert.AreEqual(user.Name, retrievedUser.Name);

    // double check nested objects
    CollectionAssert.AreEqual(user.Tags, retrievedUser.Tags);

    // check out the attachment round-trip
    var info = database.AddAttachment(revision, "my.txt", WriteFile("my.txt"));
    Assert.AreEqual(info.Ok, true);
    database.GetAttachment(info, "my.txt", ContentsShouldBeEqual("my.txt"));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;JSON Serializer for CouchDB&lt;/h1&gt;

&lt;p&gt;That's how JSON (&lt;em&gt;JavaScript Object Notation&lt;/em&gt;) looks like. As you can see, it is yet another human-readable and platform-independent alternative for exchanging serialized data over the wire. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
     "firstName": "John",
     "lastName": "Smith",
     "address": {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": 10021
     },
     "phoneNumbers": [ "212 555-1234", "646 555-4567" ]
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are quite a few JSON serializers for .NET available out there. Some of these include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://james.newtonking.com/projects/json-net.aspx" target="_blank" class="offsite-link-inline"&gt;Json.NET&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jayrock.berlios.de/" target="_blank" class="offsite-link-inline"&gt;JayRock&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.aspx" target="_blank" class="offsite-link-inline"&gt;DataContractJsonSerializer&lt;/a&gt; from WCF;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/jsonsharp/" target="_blank" class="offsite-link-inline"&gt;JSONSharp&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://litjson.sourceforge.net/" target="_blank" class="offsite-link-inline"&gt;LitJSON&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx" target="_blank" class="offsite-link-inline"&gt;JavaScriptSerializer&lt;/a&gt; from &lt;em&gt;System.Web.Extensions.dll&lt;/em&gt; as &lt;a href="http://abdullin.com/journal/2009/7/24/couchdb-in-the-cloud-persisting-from-net-code.html#comment4927408"&gt;mentioned by Oleg&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each JSON serializer has its own advantages (primary one being - they already are implemented) and disadvantages for the purpose of integrating with CouchDB. &lt;/p&gt;

&lt;p&gt;If I were to implement a proper .NET wrapper for CouchDB form the start, I would definitely go with my own serializer tailored for CouchDB needs (using JayRock architecture as a guideline but making it more strongly-typed and simple). However in this research article we'll stick with the &lt;em&gt;DataContractJsonSerializer&lt;/em&gt; from Windows Communication Foundation. &lt;/p&gt;

&lt;p&gt;This serializer has following major disadvantages that should be kept in mind: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This serializer does not handle anonymous types. This takes away all fun of working with schema-less databases.&lt;/li&gt;
&lt;li&gt;Serializer requires classes to be declared with a &lt;em&gt;DataContractAttribute&lt;/em&gt; that has members decorated with &lt;em&gt;DataMemberAttribute&lt;/em&gt;. This does not allow custom mapping routines. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me explain why Attribute-based type declaration creates too much development friction for such a flexible database as CouchDB. &lt;/p&gt;

&lt;p&gt;Just compare these two snippets below. First one is about declaring objects for CouchDB API in WCF-compatible (and C#-styled) way:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public sealed class DatabaseInfo
{
    [DataMember(Name="name")]
    public string Name { get; set; }
    [DataMember(Name="doc_count")]
    public int DocCount { get; set; }
    [DataMember(Name = "doc_del_count")]
    public int DocDelCount { get; set; }
    [DataMember(Name="update_seq")]
    public int UpdateSeq { get; set; }
    [DataMember(Name = "compact_running")]
    public bool IsCompacting { get; set; }
    [DataMember(Name = "disk_size")]
    public int DiskSize { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Second snippet is about declaring objects using F# projects (which are first-class citizens in Visual Studio now) and style:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;type db_information = 
  {
    db_name : string;
    doc_count : int;
    doc_del_count : int;
    update_seq : int;
    compact_running : bool;
    disk_size : int
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In my opinion, second type of declaration feels somewhat closer to the ideas behind CouchDB. More than that, F# compiler would automatically implement CompareTo, Equals and GetHashCode for these .NET objects. However using this kind of object declaration would require either extending an existing Json serializer or writing a new one.&lt;/p&gt;

&lt;p&gt;Given all that, &lt;em&gt;DataContractJsonSerializer&lt;/em&gt; from WCF is still perfect for this specific &lt;em&gt;research&lt;/em&gt; article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RestClient&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most simple implementation of a &lt;em&gt;RestClient&lt;/em&gt; class is a wrapper around WebRequest class that could look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public sealed class RestClient
{
    public readonly Uri Url;

    public RestClient(Uri url)
    {
        Url = url;
    }

    public Restponse Do(string query, string method, Action&amp;lt;Stream&amp;gt; writer);    
    public Restponse Do(string query, string method);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Two &lt;em&gt;Do&lt;/em&gt; overloads are almost the same. The second one just does not create a stream for writing contents. Second overload looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public Restponse Do(string query, string method, Action&amp;lt;Stream&amp;gt; content)
{
    try
    {
        var request = (HttpWebRequest) WebRequest.Create(new Uri(Url, query));
        request.Method = method;
        request.ContentType = "application/json";

        using (var writer = request.GetRequestStream())
        {
            content(writer);
        }

        return new Restponse((HttpWebResponse) request.GetResponse());
    }
    catch (WebException e)
    {
        // till we get to rewrite web requests to live without exceptions
        return new Restponse((HttpWebResponse) e.Response);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;where the &lt;em&gt;Restponse&lt;/em&gt; is a simple wrapper class used to ensure that code stays decoupled from &lt;em&gt;HttpWebResponse&lt;/em&gt; class and that developer does not forget to dispose the request:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public sealed class Restponse : IDisposable
{
    public readonly int StatusCode;
    readonly HttpWebResponse _response;

    public Restponse(HttpWebResponse response)
    {
        _response = response;
        StatusCode = (int)_response.StatusCode;
    }    

    public void RunReader(Action&amp;lt;Stream&amp;gt; read)
    {
        using (var s = _response.GetResponseStream())
        {
            read(s);
        }
    }
    public T RunReader&amp;lt;T&amp;gt;(Func&amp;lt;Stream,T&amp;gt; read)
    {
        using (var s = _response.GetResponseStream())
        {
            return read(s);
        }
    }    
    public void Dispose()
    {
        ((IDisposable)_response).Dispose();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By the way, as we've mentioned in the schematics before, &lt;em&gt;RestClient&lt;/em&gt; is a good place to hide behind the &lt;em&gt;IRestClient&lt;/em&gt; interface and squeeze in a wrapper in between. &lt;/p&gt;

&lt;p&gt;Thise way you'll be able to add exception handling and reliability layer to all requests. This layer could be implemented using IoC-injectable Action Policies intercepting all communication failures (i.e.: network break-downs) and &lt;a href="http://abdullin.com/journal/2008/12/1/net-exception-handling-action-policies-application-block.html"&gt;retrying the last request a few times before giving up&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CouchServer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we have two simple pieces needed to talk to CouchDB. Let's actually try doing this. Our knowledge about the server-level CouchDB API will be encapsulated in &lt;em&gt;CouchServer&lt;/em&gt; and &lt;em&gt;CouchDatabase&lt;/em&gt; classes. &lt;em&gt;CouchServer&lt;/em&gt; starts like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public sealed class CouchServer
{
    readonly ISerializer _serializer;
    readonly IRestClient _client;    

    public CouchServer(IRestClient client, ISerializer serializer)
    {
        _serializer = serializer;
        _client = client;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As we remember, &lt;em&gt;ISerializer&lt;/em&gt; is a simple interface abstracting away &lt;em&gt;DataContractJsonSerializer&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;In the environment without &lt;a href="http://abdullin.com/wiki/inversion-of-control-ioc.html"&gt;Inversion of Control&lt;/a&gt; &lt;em&gt;CouchServer&lt;/em&gt; could be created with a factory method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public static CouchServer ConnectToServer(string url)
{
  var rest = new RestClient(new Uri(url));
  return new CouchServer(rest, new WCFJsonSerializerWrapper());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By the way, that's a good approach for creating &lt;em&gt;developer-friendly libraries&lt;/em&gt;. We implement all functionality as separated and decoupled components (as in &lt;a href="http://abdullin.com/wiki/component-driven-development.html"&gt;component-driven development&lt;/a&gt;) ready to be consumed by whatever &lt;a href="http://abdullin.com/wiki/inversion-of-control-ioc.html"&gt;IoC Container&lt;/a&gt; the developer likes. Extensibility and flexibility come in there natively.&lt;/p&gt;

&lt;p&gt;Should the project be too simple for wring up the proper IoC infrastructure, developer-friendly library will have some static factory class to use. This class would serve as a logical entry-point into the library and would host hard-coded creation of components (using recommended configurations and settings).&lt;/p&gt;

&lt;p&gt;Let's get back to our code. That's how the &lt;em&gt;CouchServer&lt;/em&gt; class goes on in C#:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public string[] GetDatabaseNames()
{
    using (var restponse = _server.Do("_all_dbs", "GET"))
    {
        return restponse.RunReader(r =&amp;gt; _serializer.Deserialize&amp;lt;string[]&amp;gt;(r));
    }
}

public void CreateDatabase(string name)
{
    using (var restponse = _server.Do(name + "/", "PUT"))
    {
        if (restponse.StatusCode != 201)                
            throw CouchException.From(restponse);
    }
}

public ServerInfo GetInformation()
{
    using (var restponse = _server.Do("", "GET"))
    {
        if (restponse.StatusCode != 200)
            throw CouchException.From(restponse);

        return restponse.RunReader(r =&amp;gt; _serializer.Deserialize&amp;lt;ServerInfo&amp;gt;(r));
    }
}

public void DeleteDatabase(string name)
{
    using (var restponse = _server.Do(name + "/", "DELETE"))
    {
        if (restponse.StatusCode != 200)
            throw CouchException.From(restponse);            
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, we are merely executing commands according to the CouchDB RestAPI documentation here. &lt;/p&gt;

&lt;p&gt;Software architect, that had to deal with the user input before, would definitely notice one really important thing that is missing here - input validation (CouchDB has quite a few naming rules). &lt;/p&gt;

&lt;p&gt;If needed, such validation could be easily added with the help of &lt;a href="http://abdullin.com/journal/2008/11/23/net-application-block-for-validation-and-business-rules.html"&gt;Lokad Rules&lt;/a&gt;. Any other framework that allows to define concise, readable and composable rules in .NET would, obviously, work as well.&lt;/p&gt;

&lt;p&gt;When we need to start working with the specific database we just use this method to create another friendly CouchDB wrapper class &lt;em&gt;CouchDatabase&lt;/em&gt;, by passing to it existing serializer and a RestServer instance with a database url:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public CouchDatabase ConnectToDatabase(string databaseName)
{
    var dbUrl = new Uri(_server.Url, databaseName + "/");
    var server = new RestServer(dbUrl);
    return new CouchDatabase(server, _serializer);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;CouchDatabase&lt;/em&gt; class is similar to &lt;em&gt;CouchServer&lt;/em&gt; but encapsulates database-level routines. Here's how it might look like in C#:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public sealed class CouchDatabase
{
  readonly IRestClient _client;
  readonly ISerializer _serializer;

  public CouchDatabase(IRestClient restClient, ISerializer serializer)
  {
    _client = restClient;
    _serializer = serializer;
  }


  public DocumentInfo SaveDocument&amp;lt;T&amp;gt;(T item, Func&amp;lt;T, string&amp;gt; id)
  {
    using (var r = _server.Do(id(item), "PUT", 
      tw =&amp;gt; _serializer.Serialize(tw, item)))
    {
      return r.RunReader(tw =&amp;gt; _serializer.Deserialize&amp;lt;DocumentInfo&amp;gt;(tw));
    }
  }

  public DocumentInfo AddAttachment(DocumentInfo info, string name, 
    Action&amp;lt;Stream&amp;gt; data)
  {
    var query = string.Format("{0}/{1}?rev={2}", 
      info.Id, name, info.Revision);
    using (var r = _server.Do(query, "PUT", data))
    {

      return r.RunReader(tw =&amp;gt; _serializer.Deserialize&amp;lt;DocumentInfo&amp;gt;(tw));
    }
  }

  public void GetAttachment(DocumentInfo info, string name, 
    Action&amp;lt;Stream&amp;gt; reader)
  {
    var query = string.Format("{0}/{1}?rev={2}", info.Id, name, info.Revision);
    using (var r = _server.Do(query, "GET"))
    {
      r.RunReader(reader);
    }
  }

  public T GetDocument&amp;lt;T&amp;gt;(string id)
  {
    using (var r = _server.Do(id, "GET"))
    {
      return r.RunReader(tw =&amp;gt; _serializer.Deserialize&amp;lt;T&amp;gt;(tw));
    }
  }

  public DatabaseInfo GetInfo()
  {
    using (var r = _server.Do("", "GET"))
    {
      return r.RunReader(tw =&amp;gt; _serializer.Deserialize&amp;lt;DatabaseInfo&amp;gt;(tw));
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, this should be enough to give you an idea, how we can interact with CouchDB server instances from .NET. &lt;/p&gt;

&lt;p&gt;By the way, interesting part of this simple approach is that it could be reused in other REST adapters as well. For example, one could keep all the infrastructure intact but add different wrapper implementations in order to talk to some other RESTful Cloud APIs (i.e. Rackspace Cloud or Windows Azure) directly.&lt;/p&gt;

&lt;p&gt;Source code behind the idea at the moment is based on a single usage scenario prototype. Thus, it is not ready for any kind of publicly shared library or framework, since &lt;strong&gt;any functionality in the shared library should be backed up&lt;/strong&gt; by real usage scenarios coming from, at least, &lt;strong&gt;two different projects&lt;/strong&gt;. Otherwise we might get inefficient code and bad development practices affecting everybody using the framework.&lt;/p&gt;

&lt;p&gt;There might be another research article on the topic about using simple .NET layer (hosted within Mono runtime and implemented as IHttpHandler) to provide cost-effective and scalable server-side functionality in the cloud with the same RESTful API (suitable for a specific set of scenarios). Stay tuned for the &lt;a href="http://feeds.abdullin.com/RinatAbdullin"&gt;updates on the topic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/ncouch/"&gt;CouchDB Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/wiki/what-is-api.html"&gt;What is API?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/cloud-computing-in-net"&gt;Cloud Computing Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/xlim/"&gt;xLim Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://wiki.apache.org/couchdb/" target="_blank" class="offsite-link-inline"&gt;CouchDB wiki&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://wiki.apache.org/couchdb/Getting_started_with_C%23" target="_blank" class="offsite-link-inline"&gt;Getting started with C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.apache.org/couchdb/HTTP_database_API" target="_blank" class="offsite-link-inline"&gt;HTTP Database API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.apache.org/couchdb/HTTP_Document_API" target="_blank" class="offsite-link-inline"&gt;HTTP Document API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API" target="_blank" class="offsite-link-inline"&gt;HTTP Bulk Document API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=wLh248OoYKg:x7RX-4v6fFI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?i=wLh248OoYKg:x7RX-4v6fFI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=wLh248OoYKg:x7RX-4v6fFI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?i=wLh248OoYKg:x7RX-4v6fFI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=wLh248OoYKg:x7RX-4v6fFI:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=wLh248OoYKg:x7RX-4v6fFI:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry><entry><title>CouchDB in the Cloud - Cheap and Flexible Persistence For .NET</title><category term="Articles" /><category term="Cloud Computing" /><category term="CouchDB" /><category term="How To" /><category term="IRepository" /><category term="Linux" /><category term="xLim" /><id>http://abdullin.com/journal/2009/7/21/couchdb-in-the-cloud-cheap-and-flexible-persistence-for-net.html</id><link rel="alternate" type="text/html" href="http://abdullin.com/journal/2009/7/21/couchdb-in-the-cloud-cheap-and-flexible-persistence-for-net.html" /><author><name>Rinat Abdullin</name></author><published>2009-07-20T23:44:10Z</published><updated>2009-07-20T23:44:10Z</updated><content type="html" xml:lang="en-US">&lt;p&gt;This post about CouchDB is a research that continues topics of &lt;a href="http://abdullin.com/xlim/"&gt;xLim&lt;/a&gt; and &lt;a href="http://abdullin.com/cloud-computing-in-net/"&gt;Cloud Computing in .NET&lt;/a&gt; series. &lt;/p&gt;

&lt;p&gt;We’ll walk over one of the possible approaches for using CouchDB from .NET applications in a cloud scenario.&lt;/p&gt;

&lt;h1&gt;What is CouchDB?&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://en.wikipedia.org/wiki/CouchDB" target="_blank" class="offsite-link-inline"&gt;CouchDB&lt;/a&gt;&lt;/strong&gt; is a database engine designed for persisting documents without a predefined schema. It uses HTTP REST API for communicating with JSON-serialized messages. CouchDB claims to be designed for scalability (this includes multi-master replication model).&lt;/p&gt;

&lt;p&gt;Simply put, you talk to CouchDB server with documents like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  "Subject":"I like Plankton",
  "Author":"Rusty",
  "PostedDate":"2006-08-15T17:30:12-04:00",
  "Tags":["plankton", "baseball", "decisions"],
  "Body":"I decided today that I don't like baseball. I like plankton."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Documents do not have predefined schema, so this is a valid one as well:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  "Author":"Rusty",
  "About": "Former baseball fan."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; although documents are unstructured, they always have a unique identifier associated with them and a revision number (CouchDB features &lt;em&gt;Multi-Version-Concurrency-Control model&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;In order to run queries against all this unstructured data, CouchDB features uses of View Servers that process and update structured views expressed in &lt;a href="http://en.wikipedia.org/wiki/MapReduce" target="_blank" class="offsite-link-inline"&gt;MapReduce&lt;/a&gt; queries (yes, that's the scalability opportunity here). These queries are like SQL in the relational world, yet they could be written in various languages (Javascript, Python, Ryby and Python are supported at the moment). &lt;/p&gt;

&lt;p&gt;&lt;a href="http://couchdb.apache.org/" target="_blank" class="offsite-link-inline"&gt;CouchDB as a project&lt;/a&gt; is a top-level open-source project within the Apache Foundation.&lt;/p&gt;

&lt;p&gt;CouchDB is written in &lt;a href="http://en.wikipedia.org/wiki/Erlang_(programming_language)" target="_blank" class="offsite-link-inline"&gt;Erlang&lt;/a&gt; and is capable of running on POSIX systems. Theoretically it could even run on Windows, but the experience is far from being smooth. Yet, it is extremely easy to get yourself a cheap DB instance running in the cloud (as we'll see later in the article).&lt;/p&gt;

&lt;p&gt;Primary disadvantages of the project are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CouchDB is a young project and it has not gone through heavy stress usage;&lt;/li&gt;
&lt;li&gt;.NET adapters are not present.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, using this technology in scenario where it does not fit well, will turn it into one big disadvantage as well.&lt;/p&gt;

&lt;h1&gt;How to run CouchDB in the Cloud?&lt;/h1&gt;

&lt;p&gt;At the moment there is no public CouchDB hosting available, yet. One future option worth of mentioning is a &lt;a href="http://hosting.couch.io/" target="_blank" class="offsite-link-inline"&gt;Couch.IO&lt;/a&gt; that will offer 10GB size databases for 30 USD per month.&lt;/p&gt;

&lt;p&gt;However, let's see how we can get us a virtual CouchDB server at a fraction of this cost.&lt;/p&gt;

&lt;p&gt;We'll use &lt;a href="http://www.rackspacecloud.com/" target="_blank" class="offsite-link-inline"&gt;Rackspace cloud&lt;/a&gt; &lt;a href="http://abdullin.com/wiki/what-is-virtual-machine-vm.html"&gt;Virtual Machine&lt;/a&gt; slice in this scenario. You'll find the sequence for setting up a temporary development machine below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; this configuration is not designed for production scenarios. You would at least need to adjust the firewall settings, change the ports, assign proper users and configure couchdb for auto-start. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create new virtual cloud server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Properties: 256 MB - $0.015 per hour - 10 GB&lt;/li&gt;
&lt;li&gt;OS: Ubuntu 9.04 (jauntu)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/07/2009-07-12_creating_cloud_VM.png" alt="Creating Cloud Server VM in Rackspace"/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Wait till confirmation email comes (a couple of minutes) and launch &lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html" target="_blank" class="offsite-link-inline"&gt;Putty&lt;/a&gt; (or any other SSH client) using the IP address from your confirmation email. Security warning will show up - Just hit "No" to accept the key temporarily. Username and password are provided in the email.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; right-click with mouse acts as "paste" in &lt;em&gt;Putty&lt;/em&gt;. This works even when system expects password input.&lt;/p&gt;

&lt;p&gt;After a successful logon you should see something like:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/07/2009-07-12_logon_to_remote_cloud_server.png?__SQUARESPACE_CACHEVERSION=1247419417372" alt="Logon to remote cloud server"/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Update everything to the latest by typing following command and hitting enter: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;apt-get update&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install everything that is required for running latest CouchDB:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;aptitude -y install build-essential&lt;/em&gt; &lt;br /&gt;
&lt;em&gt;apt-get -y install libmozjs-dev libicu-dev libcurl4-openssl-dev erlang&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get the latest release and compile it:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;wget http://mirrors.24-7-solutions.net/pub/apache/couchdb/0.9.0/apache-couchdb-0.9.0.tar.gz&lt;/em&gt; &lt;br /&gt;
&lt;em&gt;tar zxvf apache-couchdb-0.9.0.tar.gz &amp;amp;&amp;amp; cd apache-couchdb-0.9.0&lt;/em&gt; &lt;br /&gt;
&lt;em&gt;./configure &amp;amp;&amp;amp; make &amp;amp;&amp;amp; sudo make install&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; You can install CouchDB 0.8 by simply executing &lt;em&gt;apt-get couchdb&lt;/em&gt;. But it will miss some of the 0.9 features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow the instance to listen to public IP:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nano /usr/local/etc/couchdb/local.ini&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this window you will need to change httpd section to look like the snippet below and save:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[httpd]
port = 5984
bind_address = 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start CouchDB by typing:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;couchdb -b&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify in the command prompt that the instance is running locally (it should return "hi" from CouchDB):&lt;/p&gt;

&lt;p&gt;&lt;em&gt;curl http://localhost:5984&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify from your local machine that CouchDB is accessible and ready by opening this Url in your browser :&lt;/p&gt;

&lt;p&gt;&lt;em&gt;http://[IP of CouchDB Server here]:5984/_utils/&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;How to install CouchDB on Windows?&lt;/h1&gt;

&lt;p&gt;Working with a real and cheap server in the cloud might be interesting. Yet it could be impractical in certain scenarios (i.e.: when working in offline mode or testing complex deployment scenarios). For that we need to learn how to install CouchDB on a local machine.&lt;/p&gt;

&lt;p&gt;Although it is possible to run CouchDB directly on Windows, the solution is too bulky and unreliable. We can simply use Ubuntu virtual machine instead, sticking to the routine above. &lt;/p&gt;

&lt;p&gt;Unfortunately Windows 7 Virtual PC is extremely limited (its primary goal is to support legacy applications by virtualizing Windows XP). So in order to create a new VM we'll use &lt;a href="http://www.virtualbox.org/" target="_blank" class="offsite-link-inline"&gt;Sun VirtualBox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download latest &lt;a href="http://www.ubuntu.com/getubuntu/download-server" target="_blank" class="offsite-link-inline"&gt;Ubuntu server distribution&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create new VM instance for Ubuntu, named "Ubuntu".&lt;/li&gt;
&lt;li&gt;Set up NAT networking for this instance and create sufficiently large HD (2 GBs should be enough).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/07/2009-07-21_running_ubuntu_VM.png" alt="VirtualBox running Ubuntu Virtual Machine for CouchDB"/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mount downloaded Ubuntu ISO into the virtual DVD and go through the bare server installation.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logon into the instance and install SSH server:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;sudo apt-get install openssh-server&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shut down the instance and configure virtual SSH forwarding so that we could use Putty to talk to the OS locally (we are assuming that the VM instance name is 'Ubuntu'). These commands have to be executed from the VirtualBox directory. Note, that there are no line breaks between "Ubuntu" and "VBoxInternal..." (I've introduced them for readability).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;VBoxManage setextradata "Ubuntu" 
"VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/Protocol" TCP
VBoxManage setextradata "Ubuntu"
"VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/GuestPort" 22
VBoxManage setextradata "Ubuntu" 
"VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/HostPort" 2222
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This binding will redirect all calls from localhost:2222 to the virtual Ubuntu:22.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure CouchDB forwarding, so that we could talk to the database, as if it were installed on the localhost:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;VBoxManage setextradata "Ubuntu"
"VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestcdb/Protocol" TCP
VBoxManage setextradata "Ubuntu"
"VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestcdb/GuestPort" 5984 
VBoxManage setextradata "Ubuntu"
"VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestcdb/HostPort" 5984
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create short-cut to the GUI-less interface of VirtualBox. Launching it will start our server-in-a-box:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;VBoxHeadless.exe --startvm Ubuntu --vrdp=off&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect Putty to localhost:2222 (port number we've configured for SSH forwarding) and perform the install routine from the previous section, starting from:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;apt-get update&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now you should be able to talk to your CouchDB (don't forget to start it) using the following address:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;http://localhost:5984/&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can open Futon interface in the browser with:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;http://localhost:5984/_utils/&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/07/2009-07-21_using_futon_to_view_couchdb.png" alt="Using Futon to view CouchDB statuc locally"/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;That should be it. Now we have a local CouchDB server that could be used as a development sandbox. We could also replicate this deployment in any cloud environment that supports &lt;a href="http://abdullin.com/wiki/cloud-computing.html"&gt;Infrastructure as a Service&lt;/a&gt; scenario with VMs.&lt;/p&gt;

&lt;p&gt;This database server does not have a predefined schema, is easy and cheap to deploy (once you know the drill) and has been designed with the scalability in mind. All this makes Couch DB an interesting technology that might fit well in &lt;a href="http://abdullin.com/xlim/"&gt;xLim set of design principles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next article we'll talk about &lt;a href="http://abdullin.com/journal/2009/7/24/couchdb-in-the-cloud-persisting-from-net-code.html"&gt;using .NET to communicate with CouchDB in a strongly-typed manner&lt;/a&gt;. You can &lt;a href="http://feeds.abdullin.com/RinatAbdullin"&gt;subscribe to this journal to stay tuned for any updates&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/ncouch/"&gt;NCouch series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/cloud-computing-in-net"&gt;Cloud Computing Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/xlim/"&gt;xLim Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ibm.com/developerworks/opensource/library/os-couchdb/index.html" target="_blank" class="offsite-link-inline"&gt;Exploring CouchDB&lt;/a&gt; at IBM&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.apache.org/couchdb/" target="_blank" class="offsite-link-inline"&gt;CouchDB Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1192" target="_blank" class="offsite-link-inline"&gt;Amazon Machine Image with CouchDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=wMA4sCozHo8:GWHwV-QRRxE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?i=wMA4sCozHo8:GWHwV-QRRxE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=wMA4sCozHo8:GWHwV-QRRxE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?i=wMA4sCozHo8:GWHwV-QRRxE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=wMA4sCozHo8:GWHwV-QRRxE:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/couchdb?a=wMA4sCozHo8:GWHwV-QRRxE:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/couchdb?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry></feed>

