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:
safe=true
: the driver sends a getLastError command after every update to ensure that the update succeeded”MongoServer.Create
: always returns the same instance of the server object when you call it with the same connection string so it’s also OK to just call MongoServer.Create again whenever you need to.”
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