hammer and anvil

Getting Started With MongoDB and the 10gen C# Driver

While most of this article still applies to the current version of the C# driver, I have written an updated version: Getting Started With MongoDB and C# Revisited

My main goals are to setup MongoDB for small scale applications that aren’t going to scale up to lots of users and multiple servers. I’ve installed MongoDB as a service and I’ve started to play around with the 10gen C# driver. There are a couple of C# drivers already out there (NoRM and the mongodb-csharp ones being the most popular) and people report varying levels of success. 10gen has also released a driver which has caught up feature-wise to the others. I decided to use this one because it’s easy to use and I do get a warm and fuzzy feeling knowing that it is from the 10gen folks. You can find the repository at https://github.com/mongodb/mongo-csharp-driver

Into the code!

The best place to get started is the 10gen C# driver tutorial at http://www.mongodb.org/display/DOCS/CSharp+Driver+Tutorial. It covers what you need to get started and sometimes a bit more.

The app I’m writing is a simple one that stores usernames and passwords along with some other information like the URL of the website to use the password and any notes that we might want to add. It’s just going to be on our internal network and won’t have any interface to the internet. That means I’m not focusing on things like encrypting the passwords, or other security measures if this were to be used anywhere else in the public.

Connecting to your database is pretty straight forward. There are many other options available, but just to get started, you just need the server name.

1
2
MongoServer server = MongoServer.Create("mongodb://myserver");
MongoDatabase db = server.GetDatabase("TheDatabase");

One of the things I like about MongoDB is that just asking for the database will create it.

So now that we have a reference to our new database, what are we going to do with it? Most of the time, we already have a model ready to be stored. Here’s my class that hold a password set.

1
2
3
4
5
6
7
8
9
10
11
public class CredentialSet
{
    public ObjectId _id { get; set; }
    public string Title { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string WebSite { get; set; }
    public string Notes { get; set; }
    public int Owner { get; set; }
    public DateTime LastUpdate { get; set; }
}

It’s a pretty basic class. The only addition from standard C# is the ObjectId class. This class represents the default MongoDB identifier. You can choose to use your own unique identifier, but for now, I’m just going to use the default.

Our next step is to create an instance of our class and save it to the database. But first, we need a place to store it. In the relational world, we would use tables inside our database to store the data. In the MongoDB world, we use the Collection. Just like the database, the act of getting the reference to it will create it if it doesn’t exist.

1
MongoCollection passwords = db.GetCollection("passwords");

As you can see, we can specify our CredentialSet class when we get our collection. Even though MongoDB is a schema-less document store, it does make life easier to have a standard, static type to work with. When we specify a class like this, we are telling the driver to use our CredentialSet as the default when pulling our documents from the database. You can still insert any type of document you want, but this style saves us some key strokes later on.

So now let’s save our document.

1
2
3
4
var password = new CredentialSet();
 
// set the property values.
passwords.Save(password);

We can now use a tool like MongoVUE to see our record in MongoDB. When we take a look at it, we see something a little unexpected. Our _id is all zeros!

1
2
3
4
5
6
7
8
9
10
11
/* 0 */
{
  "_id": "000000000000000000000000",
  "Title": "A password",
  "Username": "username",
  "Password": "password",
  "WebSite": "www.google.com",
  "Notes": "This is a password!",
  "Owner": "1",
  "LastUpdate": "Tue, 1 Feb 2011 10:47:20 GMT -05:00"
}

Doing some research, I found some references to a known issue with the 10gen client, and a simple fix. We just need to add an attribute to our model’s _id property. Here’s the updated CredentialSet.

1
2
3
4
5
6
7
8
9
10
11
12
public class CredentialSet
{
    [BsonId]
    public ObjectId _id { get; set; }
    public string Title { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string WebSite { get; set; }
    public string Notes { get; set; }
    public int Owner { get; set; }
    public DateTime LastUpdate { get; set; }
}

This tells the driver that we want to use the _id property as the internal MongoDB identifier. After delete our exiting item using MongoVUE, we can run our sample again and examine the record.

1
2
3
4
5
6
7
8
9
10
11
/* 0 */
{
"_id": "4d38833880844214f0a8c60b",
"Title": "A password",
"Username": "username",
"Password": "password",
"WebSite": "www.google.com",
"Notes": "This is a password!",
"Owner": "1",
"LastUpdate": "Tue, 1 Feb 2011 10:47:20 GMT -05:00"
}

Much better. Now we can try to pull that document out. There are lots of queries you might want to do. Way more than I can go through. I’m just going to show two simple examples. The first is pulling out all documents, and the second is finding a specific record based on a single field.

Let’s start with all records.

1
var allPasswords = passwords.FindAll();

It doesn’t get much easier than this! Again, we can use this simple method because we’ve specified a default document class. From here, we have a collection of CredentialSet objects that we can work with using standard methods such as foreach or Linq to Objects. So now let’s get a specific document.

To get a specific document, we need to build up a Query object to tell the driver how to create the JSON that MongoDB will use to find our document. From there, we use the FindOne method on the collection.

1
2
var query = Query.EQ("Title", "A password");
var oneDocument = passwords.FindOne(query);

There are lots of options when creating a Query. The one we used here, EQ, does a simple Equality comparison. It finds all documents where the Title field exactly matches ‘A password’. Since this was the Title we put in above, that’s the one we get back. Just about all of the options for querying are available. The 10gen C# driver page does a good job covering them.

Wrapping up

This was my first use of MongoDB. With the basics of saving and retrieval down, I can move forward on getting an app up and running. I know that this is really simple and it doesn’t cover any of the features MongoDB is known for such as master/slave replication or sharding. I also don’t do any error checking.

Something as simple as this can be done with any relational database. But in order to do this, I’d need to hook in an ORM such as nHibernate or EF4. That means extra code. The MongoDB driver handles all of the class to JSON mapping automatically. That’s what I’m looking for with this.

Standard tutorial disclaimer: None of this code is what I consider Production Ready. It did give me a starting point to move forward from. Hopefully it helps someone else as well.


comments powered by Disqus