FunnelWeb on RavenDB

What is FunnelWeb?

FunnelWeb is a blog engine written using ASP.Net MVC3. I went through the source code and I quite liked it. So I used it for my blog. FunnelWeb uses nHibernate for data access over MSSQL.

So what is FunnelWeb on RavenDB?

Ever since I heard about RavenDB (RDB) I was very interested to give it a go and learn about it. So I started reading about it; but reading alone was not enough to learn about database engine; I had to do something with it. I needed a project big enough to guarantee some exposure to the engine yet not too big to take a lot of time. FunnelWeb on RavenDB was my attempt to learn RDB.

I tried to change as little as possible on the FunnelWeb itself; so what you see there is still more than %90 FunnelWeb. The reason I did not change FunnelWeb much was that I was hoping to keep the two versions compatible so that FunnelWeb on RavenDB can live next to FunnelWeb with little to no maintenance load. That attempt failed (more on this later), and I soon changed my goal and worked on the project only as a learning experience and nothing more.

Is it working?

I have tried the engine on my local machine and it works; but I must admit it is not production quality. After all, it was just for learning.

You can access the code here. You can see that I have not merged from trunk for over a month.

Some of the main changes

I removed everything NH related including NH mappings. All the references to NH, Castle proxy, Antlr, Iesi collection and so on and so forth are gone.

I also removed quite a few classes from DatabaseDeployer project of FunnelWeb because I no longer needed to deal with SQL scripts. I then removed the project and moved the remaining classes to where they belonged: the website project.

Well, I still needed to populate some default data; so I replaced the SQL scripts with the following class:

Easy data handling

I must admit it is kind of hard to compare the two due to difference in the models; but the fact is that using RDB I am achieving the same result with a much shorter and readable method. As an example, GetEntry in FunnelWeb:

I am not getting the comments though as it is not part of my document. More on this below.

The bad

RDB makes some assumptions about the objects it persists (by which I am a bit annoyed, and I hope that either I am wrong or it changes). One of the main changes I had to make on the PM was that ids had to changes from int (to support auto number in SQL) into string (to support auto string id in RDB). In addition to that, only the root class should have id. The other entities in the graph are stored and fetched as part of the graph. This meant that I had to make quite a few changes only to comply with RDB. I had to change PM because the whole persistence mechanism had changed and even repositories could not shield me from the law of leaky abstractions.

Class dependencies had to change too. Key/value stores in general (and document databases in particular) store each object graph as one entry. This effectively means you cannot have very deep object graphs. Your object graph also cannot include a lot of interrelated objects or you will end up saving your entire model into one huge document. The rule of thumb is that you should have an object graph/document per aggregate, and there should not be any direct reference between aggregates (even to the aggregates roots). So the object model had to change to instead of having direct links to other entities have their ids. I had to do this only in one place (because in a blog engine everything is about blog entry):

I had to make comment a different document because FunnelWeb deals with them as separate entities (from the admin section). I tried to store them as part of Entry graph; but I had some technical issues. It was still possible with a small hack (as mentioned in my response in the google group discussion); but I think this solution is ok.

So basically if you want to migrate an existing application written with relational mindset to RDB or any other document database you are in a rather big trouble. From RDB documentation:

“The most typical error people make when trying to design the data model on top of a document database is to try to model it the same way you would on top of a relational database.
Raven is a non-relational data store. Trying to hammer a relational model on top of it will produce sub-optimal results. But you can get fantastic results by taking advantage of the documented oriented nature of Raven.”

Conclusion

This was a little playground for me to learn about RDB. There are some little samples here and there on the web, but I did not find any real example, and I hope this application helps someone get started with RDB.

You can checkout complete code from the project’s homepage at google code here.