Creating a MongoDB provider for Blogengine.Net – Part 1
The code in this post is of demo quality and should not be taken as production ready code. It’s a first take on the project and will evolve during a series of posts.
Blogengine.net is an open source blogging platform written in asp.net. The engine comes with two Data store providers a DB provider and an XML provider. Since the engine is using the provider model, it should be fairly easy to write a new data store provider.
As you may have noticed by some of my previous posts, I’m really interested in alternatives to relational databases, the so called NoSql movement.
Getting all the pieces together.
First download the Blogengine.net source code from codeplex.com, a mongodb driver for .net and mongodb.
At the moment I’m aware of two drivers for .net, the more mature mongodb-csharp and a more resent one NoRM. NoRM is trying to provide a more OO experience, avoiding the use of strings as much as possible and embracing Linq, it’s still very young but very promising. You can check an article by Rob Connery to learn some of the capabilities. We will be using mongodb-csharp in this example. (Build from 2010-03-01).
Be certain of download the proper version of MongoDB for your OS 32 or 64 bits.
Installing MongoDB
Unzip the files downloaded into a folder of your choice. I’m using c:\MongoDB.
Create a data and db folders under c, you should have something like c:\data\db
Run mongod.exe from the mobogodb bin folder.
c:\MongoDB\bin>mongod.exemongod.exe —help for help and startup options
Fri Mar 05 23:09:29 Mongo DB : starting : pid = 0 port = 27017 dbpath = /data/db/ master = 0 slave = 0 64-bit
Fri Mar 05 23:09:29 db version v1.2.4, pdfile version 4.5
Fri Mar 05 23:09:29 git version: 5cf582d3d96b882c400c33e7670b811ccd47f477
Fri Mar 05 23:09:29 sys info: windows (6, 0, 6002, 2, ‘Service Pack 2’) BOOST_LIB_VERSION=1_39
Fri Mar 05 23:09:29 waiting for connections on port 27017
To stop the daemon just type Ctrl+c.
Setting up the project.
You can download the project as I have it set from my codeplex repo using Mercurial to save you some time.(Changeset 59b63f72169f)
What I did was to create a new folder \lib under the solution root (of the BlogEngine.Net code), added Nunit, Rhino Mocks and the MongoDb drivers libraries. Them from within VS I added an Specs project to hold my test and a second project to hold the code for the provider.
You should have something like this right now.
And the following directory structure.
You may not have the Resharper files and folders, that depends if you have Resharper installed or not.
Lets write the first test for our MongoDBProvider and generate the class, it needs to inherit from BlogProvider.
Even when I have the source I’m treating BlogEngine.Net as a close system. This change a little bit the way I will develop such a provider. I have control of the code there are a bunch of stuff that I will probably refactor or move around. But in this case I can’t since I don’t want to fork the project.
The first test will be to insert a new post. The code will look something like this.
public override void InsertPost(Post post){
using (var db = new MongoDB())
{
db.Insert(post);
}
}
Let’s take a look at the MongoDB class.
public class MongoDB : IDisposable{
private Mongo _server;
private Database _db;public MongoDB()
{
_server = new Mongo();
}private Database Db()
{
if (_db != null) return _db;
var server = new Mongo();
server.Connect();
db = server.getDB(BlogSettings.Instance.Name.Replace(" ", ""));
return _db;
}public void Insert<TEntity>(TEntity entity)
{
Document document = DocumentMapperFactory.GetMapper<TEntity>().Map(entity);
Db().GetCollection(entity.GetType().Name+"Docs").Insert(document);
}public void Dispose()
{
_server.Disconnect();
_server.Dispose();
}
}
In line 27 I made sure we disconnect from the db. Note in line 21 that I’m getting a mapper from a factory. This is an obvious requirement since we need a mechanism to map from our objects to the documents and back.
In the next article we will take a look at the Mapper class for Post, save and update our first entity.