danielwertheim

danielwertheim


notes from a passionate developer

Share


Sections


Tags


Disclaimer

This is a personal blog. The opinions expressed here represent my own and not those of my employer, nor current or previous. All content is published "as is", without warranty of any kind and I don't take any responsibility and can't be liable for any claims, damages or other liabilities that might be caused by the content.

Getting started (again) with MongoDb in .Net on Windows

It has been a while since I used MongoDb and wrote my C# driver, so I thought I would take a look at what has happened and to checkout how the official MongoDb driver from 10Gen works.

No this does not mean that I’m putting my open source document provider SisoDb on hold. It’s very much alive.

Install MongoDb, locally

First things first, lets install MongoDb on our system. No, need to write it all over again. For detailed information, head to the offical docs here.

I just downloaded mongodb-win32-x86_64-2.2.0 from http://www.mongodb.org/downloads, which was around 62Mb in size. You could also use Chocolatey and install this package.

Folder structure

I’ve extracted the bin folder from the downloaded zip and just placed it under a MongoDb folder. After that I’ve created a config file and a simple bat file.

MongoDb.config:

dbpath=D:DevelopmentDatabasesMongoDbData
logpath=D:DevelopmentDatabasesMongoDbLogsmongo.log

Start server.bat:

binmongod.exe --config mongodb.config
pause

Start client.bat

Ok, good to go. We can now start it using our bat file. You could also install mongod.exe as a service. But for now I will stick to starting it manually.

Does it work?

Lets try it. Start the server and the client, mongo.exe. Then use the client to issue the following:

db.persons.save({first:'Daniel', last:'Wertheim'})
db.persons.find({last:'Wertheim'})

Congratulations! You have just stored and retrieved your first document with MongoDb. Lets update something as well. Lets do something more. Find actually returns a cursor that would return every document mathing the query. Let’s say we wanted just me (the person that is), we could do it in the following ways:

//A
var p = db.persons.find({last:'Wertheim'})[0]
//B
var p = db.persons.find({last:'Wertheim'}).limit(1)
//C
var p = db.persons.findOne({last:'Wertheim'})

Now, that we have p we can inspect that document’s content by just typing p in the console. If you do that you should see something like this:

{
    "_id" : ObjectId("504746f212e7a1aeb9572368"),
    "first" : "Daniel",
    "last" : "Wertheim"
}

You could now work with the document as an object and update values etc. and then update the document in the collection using save.

d.first = 'Dan'
d.age = 32
db.persons.save(d)

Let’s move on

Not so exciting right? Lets at least use it as a developer. We will start by looking at a simple C# console. Start your “favorite” editor, Visual Studio 2010 or 2012 (I’ll be using 2012) and just start a simple console project. Next use NuGet and install the offical MongoDb driver package.

install-package mongocsharpdriver

Now we need to connect to our server and get a reference to our database:

var server = MongoServer.Create("mongodb://localhost/?safe=true");
var db = server.GetDatabase("test");

Some comments from the docs:

Lets take a quick look at two ways of accomplishing what we did above. Remember that our document now looks like this:

{
    "_id" : ObjectId("504746f212e7a1aeb9572368"),
    "first" : "Dan",
    "last" : "Wertheim",
    "age" : 32
}

Using BSONDocument

You can interact with MongoDb using a dynamic model, where you reference members with “magical strings”.

static void Main(string[] args)
{
    var server = MongoServer.Create("mongodb://localhost/?safe=true");
    var db = server.GetDatabase("test");

    UpdateUsingBsonDoc(db);
    UpdateUsingEntity(db);
}

private static void UpdateUsingBsonDoc(MongoDatabase db)
{
    var persons = db["persons"];
    var p = persons.Find(Query.EQ("first", "Dan")).First();
    p["first"] = "Daniel";
    persons.Save(p);
}

Using a typed model

You can of course also work with entities. Lets define a class representing our person:

public class Person
{
    public ObjectId Id { get; set; }
    public string First { get; set; }
    public string Last { get; set; }
    public int Age { get; set; }
}

ObjectId is a special MongoDb construct, since their Id isn’t a real Guid. Now, lets do the same using our model. Note!First has now the value "Daniel".

private static void UpdateUsingEntity(MongoDatabase db)
{
    var persons = db.GetCollection<Person>("persons");
    var p = persons.Find(Query<Person>.EQ(i => i.First, "Daniel")).First();
    p.First = "Dan";
    persons.Save(p);
}

This will fail, misserably! Why? Well, we have been using lower-case names of our “model” in MongoDb whilst in C#, they start with an uppser-case; hence we got: "first" != "First". Fear not my friends. Conventions to the rescue. Add this, e.g before you create the server.

var conventions = ConventionProfile.GetDefault();
conventions.SetElementNameConvention(new CamelCaseElementNameConvention());
BsonClassMap.RegisterConventions(conventions, t => true);

This is cheating! The CamelCaseElementNameConvention will work for us for now, but it’s actually for making the following map: "firstName" --> "FirstName". Again, fear not my friends. Lets create one our selves.

public class LowerCaseElementNameConvention : IElementNameConvention
{
    public string GetElementName(MemberInfo member)
    {
        return member.Name.ToLower();
    }
}

Now, use that instead and you are all set.

Summary

We have now gone through how to install and how to start interacting with MongoDb using the console as well as how to use the NuGet package for the offical MongoDb driver to get started with using it from C#. We have also learned how to register custom conventions when we have different conventions in our MongoDb schema vs our C# scheme. (Did you just notice there actually is a conceptual scheme in “schemaless” MongoDb). Next we will have a look at more querying and hopefully some performance.

//Daniel

View Comments