Saturday, 24 November 2012

CRUD against MongoDB via C#

In my previous post, I gave some of my first thoughts about NoSQL in relation to MongoDB. In this post we will look at how you can perform basic CRUD operations against a MongoDB collection using the official C# driver. The purpose of this post is for me to use it as a handy reference when working with MongoDB in the future - hopefully you'll also find it useful. I will assume that the reader has some familiarity with using MongoDB on the shell.

Throughout the post I'll be using a simple collection of documents where each document stores some basic information about an aircraft. If you load the MongoDB shell and execute the following statements then we'll have a common ground to start with:

db.planes.insert({
    'Manufacturer':'Lockheed Skunk Works',
    'Model':'Blackbird SR-71',
    'FirstFlight': new Date('12/22/1964')
})
db.planes.insert({
    'Manufacturer':'Lockheed Skunk Works',
    'Model':'X-55 ACCA',
    'FirstFlight': new Date('06/02/2009')
})
At this point, you should have a database called mongotest with one collection containing two JSON documents. You can verify this by executing:
db.planes.find().pretty()
We'll now access and modify the planes collection using the C# driver. You can download the driver from here or add it to your solution using the NuGet package (it's easy to do using the NuGet package manager in Visual Studio). For this post, I'm using version 1.6.1 of the official MongoDB C# driver. Assuming you now have added references to MongoDB.Bson.dll and MongoDB.Driver.dll, add the following three using statements at the top of your class (FYI, I practiced with a standard console application directly within the Main method):
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
Now we can define a class that will map to a single plane document. We will use this class along with the MongoDB generic C# driver methods to insert, retrieve, update and remove documents from our planes collection.
public class Plane
{
    public ObjectId Id { get; set; }
    public string Manufacturer { get; set; }
    public string Model { get; set; }
    public DateTime FirstFlight { get; set; }
}
Note how we're using the MongoDB.Bson.ObjectId type for our identifier property (we're relying on MongoDB to add unique id's to newly inserted plane documents). Also note that the Plane class must support a parameterless constructor for the driver to be able to work with it.

Let's now take a look at how you can insert a new plane document into the planes collection using the driver. We'll first get a handle on the planes collection, I have the following four lines at the top of my Main method that gives me the required reference (planesCollection):
var connectionString = "mongodb://localhost/?safe=true";
var server = MongoServer.Create(connectionString);
var mongotestdb = server.GetDatabase("mongotest");
var planesCollection = mongotestdb.GetCollection<Plane>("planes");
To insert a new document into the planes collection (note that the Id property will be filled-in by the insert method):
planesCollection.Insert(new Plane {
    Manufacturer = "Unknown",
    Model = "Tornado IDS/ECR",
    FirstFlight = new DateTime(1974, 8, 14)
});
To retrieve a list of all the documents in the planes collection:
var planes = planesCollection.FindAll().ToList();
To retrieve a list of filtered documents - let's say we want only the planes that are manufactured by Lockheed:
var lockheedPlanes = planesCollection.Find(
    Query.EQ("Manufacturer""Lockheed Skunk Works"))
        .ToList();
To update a document (as a whole block) in the planes collection:
var planeToUpdate = planesCollection.FindOne(
    Query.EQ("Manufacturer""Unknown")
);
planeToUpdate.Manufacturer = "Panavia Aircraft GmbH";
planesCollection.Save(planeToUpdate);
Note that you can also perform a partial update to a document (not as a block), refer to the Update method on the MongoCollection class.

Finally, to remove a set of documents based on a query from the planes collection - in this case we'll remove all planes manufactured by Lockheed from the collection:
planesCollection.Remove(
    Query.EQ("Manufacturer""Lockheed Skunk Works")
);