Archive for March, 2011

CouchDb using C# in 15 minutes

Monday, March 14th, 2011

I’ve spent quite a lot of time experimenting with document databases at the moment, almost exclusively RavenDb of late.  We’re currently looking at sweeping architecture changes at work, and unfortunately it doesn’t look like Raven is going to be suitable (nothing to do with the product, which is excellent, just a target audience with a specific ambivalence to Windows server exclusive products).  Knowing that a lot of Ravens design decisions were based around using CouchDb, and knowing that CouchDb might be a better fit for the scenario I have in mind, I set out to see how easy Couch is to use on Windows.

Short answer? Very very easy, so here’s a few quick steps for someone that wants to get up and running quickly.

First, go grab a copy of your platform-specific installer from CouchBase and install it. This is a 2-3 click process, and as the installer exits your browser pops up into “Futon” the Couch web UI.

Then go to https://github.com/foretagsplatsen/Divan , clone / download the Divan source code and build it. Divan is a handy open source project aimed at wrapping the Couch API (which is RESTful, so if you want to roll your own client library feel free). Divan is quite bare to the metal and relies on Json.Net for de/serializing documents.

Launch Visual Studio and new up a project of your choice. I’ve chucked together a few utility classes while experimenting to deal with persistence in order to get a syntax that looks like this:

   1: const string host = "localhost";

   2: const int port = 5984;

   3: var server = new CouchServer(host, port);

   4: var db = server.GetDatabase("myfirstdatabase");

   5:  

   6: var document = new SomeRandomAggregateRoot

   7:                    {This = "Is cool!", Subclass = new SomeRandomClass {IsAwesome = "hell yeah!"}};

   8:  

   9: using (var couchRepo = new CouchRepository<SomeRandomAggregateRoot>(db))

  10: {

  11:     var id = couchRepo.Save(document);

  12:     var returnedCouchDoc = couchRepo.Retrieve(id);

  13:     ViewData["Message"] = returnedCouchDoc._id;

  14: }

  15:  

  16: return View();

Which I’m pretty happy with as it seems very usable and maps pretty simply from the underlying Json documents.

I have a base class and an interface at the bottom of the object graph that look like this

   1:  

   2:     public class CouchAggregateRoot : ICouchAggregateRoot

   3:     {

   4:         public string _id { get; set; }

   5:         public string _rev { get; set; }

   6:     }

   7:  

   8:     public interface ICouchAggregateRoot

   9:     {

  10:         string _id { get; set; }

  11:         string _rev { get; set; }

  12:     }

and two little repository classes that look like this:

   1: public class CouchRepository<T> : CouchRepository where T : CouchAggregateRoot

   2: {

   3:     public CouchRepository(ICouchDatabase couchDatabase):base(couchDatabase)

   4:     {

   5:     }

   6:  

   7:     public T Retrieve(string id)

   8:     {

   9:         return Retrieve<T>(id);

  10:     }

  11:  

  12:     public string Save(T @object)

  13:     {

  14:         return Save<T>(@object);

  15:     }

  16: }

  17:  

  18: public class CouchRepository: IDisposable

  19: {

  20:     protected readonly ICouchDatabase CouchDatabase;

  21:  

  22:     public CouchRepository(ICouchDatabase couchDatabase)

  23:     {

  24:         CouchDatabase = couchDatabase;

  25:     }

  26:  

  27:     public string Save<T>(T @object) where T : CouchAggregateRoot

  28:     {

  29:         var couchDocument = new CouchDocumentWrapper<T>(@object);

  30:         CouchDatabase.SaveDocument(couchDocument);

  31:         return couchDocument.Id;

  32:     }

  33:  

  34:     public T Retrieve<T>(string id) where T : CouchAggregateRoot

  35:     {

  36:         var rawDocument = CouchDatabase.GetDocument(id);

  37:         var @object = JsonConvert.DeserializeObject<T>(rawDocument.ToString());

  38:         @object._id = rawDocument.Id;

  39:         @object._rev = rawDocument.Rev;

  40:         return @object;

  41:     }

  42:  

  43:     public void Dispose()

  44:     {

  45:         // Should probably get round to implementing this...

  46:     }

  47: }

They’re obviously not entirely fleshed out, and the Divan project obviously encapsulates more of Couches functionality than those two methods alone.

When you execute the code snippet above (which for the sake of this example was just in a random ASP.NET MVC Controller’s Get method) you’ll see a new database called “myfirstdatabase” created in Futon with your newly created document inside it.

This is obviously just scratching at the surface, but I’ve been exceptionally pleased at how easy it is to get a File –> New Project up and running using readily available tools.

Code in full on GitHub for posterity