I have been wanting to have a play with Object Databases for a while now, and today I have done just that. One of the obvious choices I had to make was which one to use. My criteria for choosing one today was simple, I wanted one which I could literally wack in and start using, which means I wanted one which either had a .NET API or was designed/ported to .NET. My decision was between two being: db4o MongoDb I went for db4o for the single reason that it looked like I could get it running and integrated the quickest. I am making a Blogging application and front end as a project with which I can test and learn with these object databases. Another requirement which I thought I would mention is that I also want to be able to use the said database in a shared hosting environment where I cannot install, run and maintain a server instance of said object database. I can do exactly this with db4o. I have not tried to do this with MongoDb at time of writing. There are quite a few in the industry now and you read an interesting post about different ones and how they are used with some of the heavy weights in the industry here : http://blog.marcua.net/post/442594842/notes-from-nosql-live-boston-2010 In the example which I am building I am using StructureMap as my IOC. To inject the object for db4o I went with a Singleton instance scope as I am using a single file and I need this to be available to any thread on in the process as opposed to using the server implementation where I could open and close client connections with the server handling each one respectively. Again I want to point out that I have chosen to stick with the non server implementation of db4o as I wanted to use this in a shared hosting environment where I cannot have such servers installed and run. public static class Bootstrapper { public static void ConfigureStructureMap() { ObjectFactory.Initialize(x => x.AddRegistry(new MyApplicationRegistry())); } } public class MyApplicationRegistry : Registry { public const string DB4O_FILENAME = "blog123"; public string DbPath { get { return Path.Combine(Path.GetDirectoryName(Assembly.GetAssembly(typeof(IBlogRepository)).Location), DB4O_FILENAME); } } public MyApplicationRegistry() { For<IObjectContainer>().Singleton().Use( () => Db4oEmbedded.OpenFile(Db4oEmbedded.NewConfiguration(), DbPath)); Scan(assemblyScanner => { assemblyScanner.TheCallingAssembly(); assemblyScanner.WithDefaultConventions(); }); } } So my code above is the structure map plumbing which I use for the application. I am doing this simply as a quick scratch pad to play around with different things so I am simply segregating logical layers with folder structure as opposed to different assemblies. It will be easy if I want to do this with any segment but for the purposes of example I have literally just wacked everything in the one assembly. You can see an example file structure I have on the right. I am planning on testing out a few implementations of the object databases out there so I can program to an interface of IBlogRepository One of the things which I was unsure about was how it performed under a multi threaded environment which it will undoubtedly be used 9 times out of 10, and for the reason that I am using the db context as a singleton, I assumed that the library was of course thread safe but I did not know as I have not read any where in the documentation, again this is probably me not reading things correctly. In short though I threw together a simple test where I simply iterate to a limit each time kicking a common task off with a thread from a thread pool. This task simply created and added an random Post and added it to the storage. The execution of the threads I put inside the Setup of the Test and then simply ensure the number of posts committed to the database is equal to the number of iterations I made; here is the code I used to do the multi thread jobs: [TestInitialize]
public void Setup()
{
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
var resetEvent = new ManualResetEvent(false);
ThreadPool.SetMaxThreads(20, 20);
for (var i = 0; i < MAX_ITERATIONS; i++)
{
ThreadPool.QueueUserWorkItem(delegate(object state)
{
var eventToReset = (ManualResetEvent)state;
var post = new Post
{
Author = MockUser,
Content = "Mock Content",
Title = "Title"
};
Repository.Put(post);
var counter = Interlocked.Decrement(ref _threadCounter);
if (counter == 0)
eventToReset.Set();
}, resetEvent);
}
WaitHandle.WaitAll(new[] { resetEvent });
sw.Stop();
Console.WriteLine("{0:00}.{1:00} seconds", sw.Elapsed.Seconds, sw.Elapsed.Milliseconds);
}
I was not doing this to test out the speed performance of db4o but while I was doing this I could not help but put in a StopWatch and see out of sheer interest how fast it would take to insert a number of Posts. I tested it out in this case with 10000 inserts of a small, simple POCO and it resulted in an average of:
899.36 object inserts / second.
Again this is just simple crude test which came out of my curiosity at how it performed under many threads when using the non server implementation of db4o. The spec summary of the computer I used is as follows:
With regards to the actual Repository implementation itself, it really is quite straight forward and I have to say I am very surprised at how easy it was to integrate and get up and running. One thing I have noticed in the exposure I have had so far is that the Query returns IList<T> as opposed to IQueryable<T> but again I have not looked into this in depth and this could be there already and if not they have provided everything one needs to make there own repository. An example of a couple of methods from by db4o implementation of the BlogRepository is below: public class BlogRepository : IBlogRepository
{
private readonly IObjectContainer _db;
public BlogRepository(IObjectContainer db)
{
_db = db;
}
public void Put(DomainObject obj)
{
_db.Store(obj);
}
public void Delete(DomainObject obj)
{
_db.Delete(obj);
}
public Post GetByKey(object key)
{
return _db.Query<Post>(post => post.Key == key).FirstOrDefault();
}
…
Anyways I hope to get a few more implementations going of the object databases and literally just get familiarized with them and the concept of no sql databases.
Cheers for now,
Andrew