The basics of MongoDb for the .Net developer

I have started to gain interest in MongoDb since I found my data classes to change often with time, and trying to change the structure of my  Oracle Db became a real pain.

In this post I’ll assume that you already know what Mongo  is and why you might want to use it over a relational database, but I’ll assume that you don’t have much, if any, experience working with Mongo in a .Net environment.

I suggest starting out by installing MongoDb as a windows service, the installation process is surprisingly simple, and I suggest working along the documentation .

To work with the windows service we will work with the mongo drivre nuget package

Schema-less – But still strongly typed!

First let’s see a simple C# class we would use for demonstration:

public class Person
{
    public string Name { get; set; }
    public Person familyMember { get; set; }
}

Now, the code to connect to the Mongo server that’s running as a service is as simple as these following:

var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("foo");
_collection = database.GetCollection("bar");

Lets go over what happens here step by step:

  1. We first supply a connection string to the MongoClient, in my case I installed the service locally and on the default port – 27017.
  2.   The Mongo server can contain many db’s – we are telling the cliet to work with a db called “foo” – at this stage the db did not exist, but as we will see, simply saving a document to “foo” will create it (so beware of typos in your production code)
  3. A Mongo Db has different collections (analog to having different tables in a relational database), in the third row we are saying two things:
    • We are working with a collection called “bar”
    • The collection stores elements of type Person – this would give as strong typing

at this stage we are ready to start working.

Saving a Person Object

Saving elements is really easy and can be done with a single line of code:

 Person p = new Person()
{
    Name = "A",
    familyMember = new Person
    {
        Name = "B"
    }
};
_collection.InsertOne(p);

This would create a record of a document in our mongo database, which looks like a JSON serialization of p:

{ “_id” : ObjectId(“5943c0613fd36abf26c5d4ee”), “Name” : “A”, “familyMember” : { “Name” : “B”, “familyMember” : null } }

What we see here:

  1. There is an “_id” property – every mongo record has an _id property, this is the one and only schema rule. Since we didn’t provide this property it was created for us. The id must be unique, and the generated Id would be generated uniquely for us.
  2. We see our object p serialized as JSON, note that there is an inner hierarchy and that our object wasn’t flatened as in a relational database

Great, we saved our first document!

Trying to retrieve the document – First try

_collection.AsQueryable().Single(person => person.Name == "A");

Let’s explain the code:

  1. We first convert the collection object into an IQueryable<Person> – this is the interface that allows us to use Linq
  2. Then we use a Linq query to find the person object by name

This code throws an error

System.FormatException: ‘Element ‘_id’ does not match any field or property of class HashTagReplace.Person.’

Why did we get an error ?

Our C# Person class did not have an Id property, the document inside the Db does have an Id property – this creates a mismatch.

But I didn’t ask for an Id!

This was my first reaction. Mongo wants an id and willing to generate it himself ? fine. But not being able to query the DB because our object does not have an id – not fine.

Let’s figure our what we can do:

  1. We can include some Id in our class
    • You might think that a Guid would be a good choice – But unfortunately this causes problems 
    • There is an ObjectId class that comes with mongo which does fit – but do we really want each data class we store to have a dependency in Mongo ? Do we want to have to change existing classes for the sake of persisting them ? I hope not. We will see how to do better
  2. We can use the shell-like query – but then we loose our type safety that we love so much, and the resulting code won’t be very readable comparing to Linq. So this doesn’t seem like the way to go either

What we will do is create a  generic wrapper class:

public static class Extensions
{
public static T Unwrap<T>(this MongoObject<T> t)
{
return t.Element;
}
}
public class MongoObject<T>
{
 [BsonId]
private ObjectId _objectId;
public T Element { get; }

public MongoObject(T element)
{
Element = element;
_objectId = new ObjectId();
}
}

Note that we also had to add an attribute telling mongo that the ObjectId property is being used as our Id. There is also an extension method to easily unwrap.

Now, to save an object we can write a generic method

public void Save<T>(T t)
{
_collection.InsertOne(new MongoObject<T>(t));
}

And finally, searching an object

 public Person FindPersonByName(string name)
{
return _collection.AsQueryable().FirstOrDefault(
personObject => personObject.Element.Name == name).Unwrap();
}

Final Words

I had fun working with mongo, and I hope I helped some of you with their first steps.

Mongo plays well with .Net and helps us balance comfort and type-safety.

I’d like to hear about your thoughts and experiences, so leave a comment if you’d like 🙂

That’s it for today, hope you had fun reading this post,

Amir

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: