This post is divided in three blocks:
- Getting MongoDB to run on your machine
- Consume it manually via the MongoDB – Console
- Consume it from C# code.
Updates!
If you are just intereseted in the C# implementation, the section for how to consume it manually using the console, can be skipped.
The section where I show you how to use it from C# code contains examples of how to get it to work using either Json.Net or Castle Dynamic proxy.
Note! The compiled libs of the MongoDB-driver (mongodb-csharp) has one tweak that I have applied. I have updated the ToString implementation of the class “Oid”, so that it returns a correct Json-format.
Getting MongoDB to run on your machine
Step 1 – Download the binaries
Go to MongoDB – downloads
I selected the 64-bit version for Windows. There is a limitations of a maximum size of 2gb per database if you use 32-bit.
Unzip and put the binaries where you want them.
My selection: “C:\MongoDB\Binaries”
Step 2 – Create the data folder
We need to manually create the folder which MongoDB will use as its storage area. By default this is: “c:\data\db” and you must create this manually. If you want to customize this, which I want, you have to execute the binary “mongod.exe” and provide it the switch “-dbpath”. I will also like it to have one directory per database that is being created, hence I use the switch “-directoryperdb”.
More about switches could be found here.
The account that is executing the mongod.exe, must have read and write access to the data folder.
My selection: “C:\MongoDB\Data”
Step 3 – Start “mongod.exe”
Start the “server” so that the core is up and running so that you can connect to it and start storing data.
So my exe is located under: C:\MongoDB\Binaries\, hence my command looks like
C:\MongoDB\Binaries>mongod -dbpath c:\MongoDB\Data -directoryperdb
Step 4 – Verfiy that Mongo is up and running
I will do this manually, using the consoleclient “mongo.exe”. It’s located with the other binaries. Just fire it up using the command line and you will be seing:
Which confirms that the server is up. Initially there are some default databases created, and as you can see one of them are “test”.
Consume MongoDB manually via the MongoDB – Console
Step 1 – Store some data using the console
Ok, lets just create a simple object with three properties: Title, Body, Tags; and lets store it under the collection “Notes” which in turn is stored in the database “SimpleNotes”:
The conceptual model will look something like this:
SimpleNotes Notes Title Body Tags Tag#1 Tag#2 ...
Start the console (mongo.exe) and type in the following commands:
use SimpleNotes
db.Notes.save({ Title: "The first document", Body: "My first document stored in MongoDB.", Tags: ["MongoDB", "Getting started"]})
db.Notes.save({ Title: "The second document", Body: "My second document stored in MongoDB."})
Read more about inserting.
Step 2 – Reconnect and query the SimpleNotes-database
Lets intend that we are opening the console and have forgotten database name etc. If you are still connected, type exit so that we can simulate a clean session. Then start mongo.exe again and exeute the following commands:
show dbs
use SimpleNotes
show collections
You will find our created database “SimpleNotes” (which is created automatically when first used) and you will also find the “Notes” collection.
Step 7 – List the stored items
Lets query out our two stored notes.
db.Notes.find()
You should now be presented with two stored documents. One that has a property “Tags” and one that doesn’t.
Step 10 – Query for specific attribute
Lets find the document that has the Tag “Getting started”.
db.Notes.find({Tags : "Getting started"})
Consume MongoDB from C# code
Step 1 – Get C# drivers for building a custom client
First you need to download a driver for C#. Go to http://github.com/samus/mongodb-csharp
I downloaded the ZIP (click “Download source”).
Unzip and open the Visual Studio solution and compile it. After having updated the ToString implementation in the “Oid” class, I took the two dll’s:
MongoDB.Driver.dll
MongoDB.Linq.dll
and I put them under: “C:\MongoDB\Drivers\csharp”. You can put them anywhere. You are just going to use “Add reference from within Visual studio”.
Step 2 – Get Json.Net
I’m using Json.Net for serialization/deserialization. You can download it from here.
Step 3 – Build the C# client
For simplicity I just created a simple console application using Visual Studio 2010. I have provided three different ways, showning you have to consume MongoDB via the C#-driver:
- Using Json
- Using Serialization/Deserialization in Json.Net
- Using Castle Dynamic proxy
All three cases will look like this: Store two notes, one with Tags and one without. The one without will then be refetched and updated with a Tag.
Fix Oid – ToString
To get things to work I had to do some tweaking. At first I hade to ensure that ToString in the class “Oid” returned a Json-representation that I code consume with Json.Net.
public override string ToString()
{
//Old: return string.Format(@"ObjectId(""{0}"")", BitConverter.ToString(value).Replace("-","").ToLower());
return string.Format("\"{0}\"", BitConverter.ToString(value).Replace("-","").ToLower());
}
Using Json
Lets look at the consuming code. Do you remember the notation in MongoDB? Database, Collections and Documents. The Document is what contains the datastructure, which isn’t the same as a traditional row, since the schema doesn’t have to be equal for all the documents in the same collection. Each document can further contain other documents or references to other documents (will be covered in future writings).
I have built some helper methods to map between the “Document” and the C# entity class “Note”. These methods are placed in the helper class: “MongoJson”.
var json = new MongoJson();
//Connect to server
var mongo = new Mongo();
mongo.Connect();
//Create clean database
var db = mongo["SimpleNotes"];
db.SendCommand("dropDatabase");
//Get collection "Notes" to hold our Note-documents
var notes = db["Notes"];
//Dump to console to see that the database is empty.
PrintNotes("Initial notes", notes);
//Create and Insert first note with properties:
//Title, Body, Tags-array
var firstNoteDocument =
json.DocumentFrom("{
Title : \"First note using Json.\",
Body : \"Some nice text.\",
Tags : [\"MongoDB\", \"Getting started\"] }");
notes.Insert(firstNoteDocument);
PrintNotes("After first insert using Json", notes);
//Create and Insert a second note with no Tags
//This note will not have Tags-represented in the schema.
var secondNoteDocument =
json.DocumentFrom("{
Title : \"Second note using Json.\",
Body : \"Some nice text.\"}");
notes.Insert(secondNoteDocument);
PrintNotes("After second insert using Json", notes);
//Read back the second note that lacked tags and provide one
var noteDocument = notes.FindOne(new Document { { "Tags", MongoDBNull.Value } });
//Update the fetch object with values from another document
//(merge of members/values)
noteDocument.Update(json.DocumentFrom("{Tags : [\"The tag\"]}"));
//Update in Db
notes.Update(noteDocument);
PrintNotes("After update of post with empty tags, using Json", notes);
mongo.Disconnect();
Using Serialization/Deserialization in Json.Net
Now I will have a static C# representation of my Note-entity.
public interface IMongoEntity
{
string _id { get; set; }
Oid GetOid();
Document GetAsDocument();
void UpdateFromDocument(Document document);
}
[Serlializable]
public class Note
: IMongoEntity
{
public virtual string _id { get; set; }
public virtual string Title { get; set; }
public virtual string Body { get; set; }
public virtual string[] Tags { get; set; }
public virtual Oid GetOid()
{
return new Oid(_id);
}
public virtual Document GetAsDocument()
{
throw new NotImplementedException();
}
public virtual void UpdateFromDocument(Document document)
{
throw new NotImplementedException();
}
}
The members GetAsDocument() and UpdateFromDocument() isn’t used in this example. They are used when we use Castle Dynamic proxy.
The consuming code will now use Document when communicating with MongoDB and will use Note in the application/domain. To map between them I will make use of Json.Net. I will only show the parts that are different this time. The consuming code looks like this:
//Create new C# Note and convert it to a document using JSON serialization/deserialization
var firstNote = new Note {
Title = "First note using Serialization",
Tags = new string[] { "MongoDB", "Getting started" },
Body = "Some nice text." };
//Convert Note to Document and insert it
var firstNoteDocument = json.DocumentFrom(firstNote);
notes.Insert(firstNoteDocument);
...
//Create and Insert second note
var secondNote = new Note {
Title = "Second note using Serialization.",
Body = "Some nice text." };
var secondNoteDocument = json.DocumentFrom(secondNote);
notes.Insert(secondNoteDocument);
...
//Read back the second note that lacked tags.
var noteDocument = notes.FindOne(new Document { { "Tags", MongoDBNull.Value } });
var note = json.ObjectFrom<Note>(noteDocument);
note.Tags = new[] { "The tag" };
//Populate the document with the changed C# object, and update in MongoDB.
json.PopulateDocumentFrom(noteDocument, note);
notes.Update(noteDocument);
Ok, time to look at the helper class. There’s no actual magic there. Just using Json.Net for serialization and deserialization.
To go from a Document to a Note I just deserialize the JSON representation of the document, which now works since I fixed the Oid-class (read about it above).
To go from a Note to a Document I need to get the JSON representation of the Note and then deserialize this to a Dictionary with key-value objects, which then are looped and assigned to the Document.
public class MongoJson
{
private const string _oidContainerName = "_id";
public T ObjectFrom<T>(Document document)
where T : class, IMongoEntity
{
if (document == null)
return null;
return JsonConvert.DeserializeObject<T>(document.ToString());
}
public Document DocumentFrom(string json)
{
return PopulateDocumentFrom(new Document(), json);
}
public Document DocumentFrom<T>(T item)
where T : class, IMongoEntity
{
return PopulateDocumentFrom(new Document(), item);
}
public Document PopulateDocumentFrom<T>(Document document, T item)
where T : class, IMongoEntity
{
if (item == null)
return document;
var json = JsonConvert.SerializeObject(item, Formatting.None);
return PopulateDocumentFrom(document, json);
}
private Document PopulateDocumentFrom(Document document, string json)
{
var keyValues = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
foreach (var keyValue in keyValues)
{
var isEmptyKeyField = (
keyValue.Key == _oidContainerName && document[_oidContainerName] != MongoDBNull.Value);
if (isEmptyKeyField)
continue;
var value = keyValue.Value ?? MongoDBNull.Value;
if (value != MongoDBNull.Value)
{
var arrayValue = (keyValue.Value as JArray);
if (arrayValue != null)
value = arrayValue.Select(j => (string)j).ToArray();
}
if (document.Contains(keyValue.Key))
document[keyValue.Key] = value;
else
{
if (value != MongoDBNull.Value)
document.Add(keyValue.Key, value);
}
}
return document;
}
}
Using Castle Dynamic proxy
One implementation left. This time I will use Castle Dynamic proxy to map between Document and Note. I do this by intercepting the properties of Note and store them in a simple statebag. The statebag is then used when converting between Notes and Documents.
First the consuming code that are different than before.
var proxyBuilder = new ProxyBuilder(new ProxyConfig());
//Create and Insert first note
var firstNote = proxyBuilder.ProxyFromClass<Note>(new EntityInterceptor());
firstNote.Title = "First note using Proxies.";
firstNote.Tags = new string[] { "MongoDB", "Getting started" };
firstNote.Body = "Some nice text.";
notes.Insert(firstNote.GetAsDocument());
...
//Create and Insert second note
var secondNote = proxyBuilder.ProxyFromClass<Note>(new EntityInterceptor());
secondNote.Title = "Second note using Proxies.";
secondNote.Body = "Some nice text.";
notes.Insert(secondNote.GetAsDocument());
...
//Read back the second note that lacked tags.
var noteDocument = notes.FindOne(new Document { { "Tags", MongoDBNull.Value } });
var note = proxyBuilder.ProxyFromClass<Note>(new EntityInterceptor());
note.UpdateFromDocument(noteDocument);
note.Tags = new[] { "The tag" };
//Populate the document with the changed C# object, and update in MongoDB.
notes.Update(note.GetAsDocument());
The interceptor that does the work, looks like this.
public class EntityInterceptor
: IInterceptor
{
private Dictionary<string, object> _stateBag = new Dictionary<string, object>();
private static readonly Type _documentType = typeof (Document);
public void Intercept(IInvocation invocation)
{
var name = invocation.MethodInvocationTarget.Name;
if(IsProperty(name))
{
var key = invocation.MethodInvocationTarget.Name.Remove(0, 4);
if (IsSetter(name))
SetValue(key, invocation.Arguments[0]);
else if (IsGetter(name))
{
var value = GetValue(key);
if (value != null)
invocation.ReturnValue = value;
}
}
else if(name == "GetAsDocument")
{
var document = new Document();
foreach (var keyValue in _stateBag)
{
document.Add(keyValue.Key, keyValue.Value);
}
invocation.ReturnValue = document;
}
else if (name == "UpdateFromDocument")
SetValuesFrom((Document)invocation.Arguments[0]);
else
invocation.Proceed();
}
private void SetValuesFrom(Document document)
{
foreach (DictionaryEntry keyValue in document)
SetValue((string)keyValue.Key, keyValue.Value);
}
private void SetValue(string key, object value)
{
if(!_stateBag.ContainsKey(key))
_stateBag.Add(key, value);
else
_stateBag[key] = value;
}
private object GetValue(string key)
{
if (!_stateBag.ContainsKey(key))
_stateBag.Add(key, null);
return _stateBag[key];
}
private bool IsProperty(string name)
{
return (name.StartsWith("set_") || name.StartsWith("get_"));
}
private bool IsGetter(string name)
{
return name.StartsWith("get_");
}
private bool IsSetter(string name)
{
return name.StartsWith("set_");
}
}
That’s it. As always all the code can be downloaded from here.
//Daniel


Great post.
I’d also suggest looking at AutoMapper for mapping between your objects.
Getting started with MongoDB – Using Json.Net and Castle Dynamic proxy…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
Nice Post
Do you have plans to implement with Mongo in the near future?
I am working on some proof of concept work at the moment, testing Mongo for a variety of persistence concerns and was planning on using interception (probably using Castle proxies), however in a different approach. If validated by the POC we will likely use Mongo in systems where publish subscribe and durable messaging are employed heavily. I blogged about it here:
http://www.simonsegal.net/blog/2010/01/26/finding-my-way-with-mongodb-and-c-part-10/
I’will use it in some personal applications. As I’m working as a consultant where I feel that the organisations are more comfortable with administrating/supporting a RDMS like SQL Server, I think it will take some time before I get the chance to use it in a business case.
//Daniel
[...] leave a comment » For history and explanation of the consuming code see my previous post. [...]
Hi,
Tried out your example but for some reason the call to the ObjectFrom method keeps throwing an exception. The stack trace is quite long but all related to Newtonsoft. The relevant lines are:
at System.Number.StringToNumber(String str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt)
at System.Convert.ToInt64(String value, IFormatProvider provider)
at Newtonsoft.Json.JsonTextReader.ParseNumber()
Hi!
I have sent you an email so that you can send me your code.
Do that and I will check it out.
//Daniel
Hi!
I have just tested the following:
1. Downloaded my example from: http://files.wertheim.se/blog/Pls-Mdb-Intro.zip
2. Unziped
3. Opened in Visual Studio 2010
4. Started Mongodb (mongod -dbpath c:\MongoDB\Data -directoryperdb)
5. Ran the Pls.MdbIntro app (F5)
6. Worked without any exceptions.
Worked.
//Daniel
Yes thanks Daniel, it works nicely now. The problem apparently is that I was using the driver from git which retrieves the oids as numbers.
Now, regarding the storing of arrays,
In the
protected virtual object ConvertToMongoDbValue(JToken token)
if (token.Type == JTokenType.Array)
{
var r = token.Select(j => (string)j).ToArray();
if (r == null || r.Length < 1)
return MongoDBNull.Value;
return r;
}
You could change it to:
if (value.Type == JTokenType.Array) {
var items = new List();
foreach (var v in value) {
var doc = PopulateDocumentFrom(new Document(), v.ToString());
items.Add(doc);
}
if (items.Count < 1)
return MongoDBNull.Value;
return items.ToArray();
}
Giving you the ability to store/retrieve nested types
Hi!
The issue has been corrected in Oid.ToString in the MongoDb-driver, but Sam was uncertain if it had reached the main-branch at Github.
Nice tip with the nested types.
//Daniel
No there is only one other problem with the ToString method on the document… It takes into consideration the current culture, which in my case has “,” as the decimal separator and this obviously screws up the json format :/
Hi,
Post the issue at: http://github.com/samus/mongodb-csharp/issues
I’m currently trying to get some time to build by own driver but I don’t know if I will get enough time….
//Daniel
There is also an error when trying to serialize an object property which is not a simple type in the ToString method. It will generate the property as
“Property” : “{” “Value”: 1, “Other”: 2 “}”
Instead of:
“Property” : { “Value”: 1, “Other”: 2 }
I’ll post these as issues to git hub. For the time being i’ve used:
private static string ToInvariantString(this Document doc) {
var json = new StringBuilder();
json.Append(“{ “);
var first = true;
foreach (string key in doc.Keys) {
if (first) {
first = false;
} else {
json.Append(“, “);
}
json.AppendFormat(CultureInfo.InvariantCulture, @”"”{0}”": “, key);
SerializeType(doc[key], json);
}
json.Append(” }”);
return json.ToString();
}
private static void SerializeType(object value, StringBuilder json) {
if (value == null) {
json.Append(“null”);
return;
}
var t = value.GetType();
if (value is bool) {
json.Append(((bool)value) ? “true” : “false”);
} else if (t.IsArray) {
json.Append(“[ ");
var first = true;
foreach (var v in (Array)value) {
if (first) {
first = false;
} else {
json.Append(", ");
}
SerializeType(v, json);
}
json.Append(" ]“);
} else if (value is Document) {
json.Append(((Document)value).ToInvariantString());
} else if (value is Oid ||
value is int ||
value is Int32 ||
value is long ||
value is float ||
value is double) {
json.AppendFormat(CultureInfo.InvariantCulture, “{0}”, value);
} else if (value is DateTime) {
json.AppendFormat(@”"”{0}”"”, ((DateTime)value).ToUniversalTime().ToString(“o”));
} else {
json.AppendFormat(CultureInfo.InvariantCulture, @”"”{0}”"”, value);
}
return;
}
Which is about the same as the .ToString method on the document, with a few edits here and there
Hope this helps someone.
[...] http://daniel.wertheim.se/2010/02/05/getting-started-with-mongodb-using-json-net-and-castle-dynamic-... http://daniel.wertheim.se/2010/02/07/mongodb-in-c-extensions-to-support-json-mapping-or-proxy-generation/ http://automapper.codeplex.com/ [...]
[...] You have MongoDb up and running. If not, just go to “http://www.mongodb.org” and download the server part and start it. You can also read the first part of my earlier writings: Getting started with MongoDB – Using Json.Net and Castle Dynamic proxy [...]
[...] Getting started with MongoDB – Using Json.Net and Castle Dynamic proxy « Daniel Wertheim. Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages. [...]