Fun with RavenDB 1

This is the first post in a small series about RavenDB – a document database in .NET. I will try to touch the same areas as I did in my series on MongoDB, possibly comparing the two where I see fit.

Now, first – let’s see if the raven can fly…

Getting started

I am extremely happy to see that Ayende has created the same installation experience as I got with MongoDB… i.e., to get the server running, perform the following steps (assuming the .NET 4 framework is installed on your system):

  1. Grab a ZIP with the lastest build here
  2. Unzip somewhere
  3. Go to /Server and run Raven.Server.exe

- and now the RavenDB server will be running on localhost:8080. That was easy. Now, try visiting http://localhost:8080 in your browser – now you should see the administration interface of RavenDB.

By the way, have you ever tried installing Microsoft SQL Server? Shudder!! :)

Connecting with the .NET client

I’m old school, so I am still using Visual Studio 2008. If you’re old school like me, add a reference to /Client-3.5/Raven.Client-3.5.dll – otherwise add a reference to /Client/Raven.Client.Lightweight.dll.

Now, to open a connection, do this:

var documentStore = new DocumentStore {Url = "http://localhost:8080"};
documentStore.Initialize();
 
using (var session = documentStore.OpenSession())
{
    // ....
}

- and then store the DocumentStore as a singleton in your program.

Inserting a document

Now, let’s try inserting a document… say we have a POCO model representation of a person that looks like this (allowing Address to be either DomesticAddress or ForeignAddress):

public class Person
{
    public string Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Address Address { get; set; }
}
 
public abstract class Address
{
    public abstract string ToString(string separator);
}
 
public class ForeignAddress : Address
{
    public string[] AddressLines { get; set; }
 
    public override string ToString(string separator)
    {
        return string.Join(separator, AddressLines ?? new string[0]);
    }
}
 
public class DomesticAddress : Address
{
    public string Street { get; set; }
    public string HouseNumber { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }
 
    public override string ToString(string separator)
    {
        return string.Join(separator, new[]
                                          {
                                              string.Format("{0} {1}", Street, HouseNumber),
                                              string.Format("{0} {1}", PostalCode, City)
                                          });
    }
}

Then, do this:

using (var session = documentStore.OpenSession())
{
    session.Store(new Person
                      {
                          FirstName = "Mogens Heller",
                          LastName = "Grabe",
                          Address = new DomesticAddress
                                        {
                                            Street = "Torsmark",
                                            HouseNumber = "4",
                                            PostalCode = "8700",
                                            City = "Horsens"
                                        }
                      });
    session.SaveChanges();
}

Now, let’s visit http://localhost:8080/raven/documents.html in the browser… it will probably look something like this:

Document in RavenDB

As you can see, RavenDB stores all documents in a single collection. Right now, there’s one person in there, and then there’s a document that RavenDB uses to generate integer IDs based on the hi-lo-algorithm. Rob Ashton has an explanation here on the design decisions made for this particular piece of RavenDB.

I like this particular decision, because it makes for some really nice human-readable, human-typeable IDs.

Note how the ID of the document is people/1 – RavenDB is smart enough to pluralize most names, which is pretty cool. Let’s click the document to see what’s in it:

Document in RavenDB

Note also how RavenDB puts type information in the document, allowing the proper subtype to be deserialized. Now, let’s try this out:

using (var session = documentStore.OpenSession())
{
    var me = session.Load<Person>("people/1");
    Console.WriteLine(@"{0} {1}
{2}", me.FirstName, me.LastName, me.Address);
}

- which results in the following console output:

Loading document [people/1] from http://localhost:8080
Mogens Heller Grabe
Torsmark 4
8700 Horsens

How cool is that?! (pretty cool, actually…)

Note that the pretty UI is based on the actual RavenDB interface to the world, which is REST-based. That means we can go to a DOS prompt and do this:

C:\>curl -X GET localhost:8080/docs/people/1
{"FirstName":"Mogens Heller","LastName":"Grabe","Address":{"$type":"raventjek.Class1+DomesticAddress, raventjek","Street":"Torsmark","HouseNumber":"4","PostalCode":"8700","City":"Horsens"}}

Now, that was a short dive into storing documents and retrieving them again by ID. We need to do more than that, though – otherwise we would have been content using a simple key/value-store. Therefore, in the next post, I will take a look at querying