Introduction
If you have already read or used RavenDb in its embedded fashion, then this article is not for you. The main reason why I publish it is the multiple problems I faced with Nuget and RavenDb client that I want to share with you. I would also like to share the way in which I fixed them.
It’s basically a step-by-step to set up a working MVC project using RavenDb. Of course, it’s not meant to show any best practices nor any architecture design using RavenDb.
The fact that RavenDb is a NoSql database makes it light and easy to use, just like MongoDb or Redis. I already wrote a How-Tos about them. You could check them out here:
So let’s start with RavenDb:
- Open Visual Studio 2013 and add an MVC 5 project.
- Open the nuget manager console and type Install-Package
RavenDB.Embedded
to install embeddable client. In some Nuget Version, you may have a problem doing it like that.
I had the following error:
Updating 'System.Spatial 5.2.0
' to 'System.Spatial 5.0.2
' failed. Unable to find a version of 'RavenDB.Database
' that is compatible with 'System.Spatial 5.0.2
'.
Seems like trying to update the system.special
package in reverse: from System.Spatial 5.2.0
to System.Spatial 5.0.2
. To solve this Nuget problem, force Nuget to run on the highest version. So retype the previous install command as follows:
Install-Package RavenDB.Embedded -DependencyVersion Highest
using Raven.Client;
public class RavenDbConfig
{
private static IDocumentStore _store;
public static IDocumentStore Store
{
get
{
if (_store == null)
throw new InvalidOperationException(
"IDocumentStore has not been initialized.");
return _store;
}
}
public static IDocumentStore Initialize()
{
_store = new EmbeddableDocumentStore
{
ConnectionStringName = "RavenDB"
};
_store.Conventions.IdentityPartsSeparator = "-";
_store.Initialize();
IndexCreation.CreateIndexes(Assembly.GetCallingAssembly(), Store);
return _store;
}
}
I will not go through every single line here (the previous snippet comes from Ayende’s sample on RavenDb web site) but basically, it initializes the EmbeddableDocumentStore
based on your connection string. This object will give you access to the document store. The connection string as always located in webconfig file:
<add name="RavenDB" connectionString="DataDir = ~\App_Data\Database" />
It’s maybe hard to see it at first glance, but at this point you have everything you need to start coding Ravendb stuff. But, you may run against a couple of problems regarding your compilation according to the versions you have installed for some DLL. Let's see the problems I met and how I resolved them:
- The first error was the newtonsoft.json. It was like:
Could not load file or assembly 'Newtonsoft.Json, Version=4.5.0.0,
Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies
To resolve it, I run these commands in the Package Manager Console:
uninstall-package newtonsoft.json -force
install-package newtonsoft.json -version 4.5.11
It seems brutal but it did the trick.
- Another error I run at was:
The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized()
is called in the application's startup code after all other initialization code
To fix it, I added the following in the Global.asax:
GlobalConfiguration.Configuration.EnsureInitialized();
At this point, I think we resolved all possible problems that may occur in the project compilation. So let's move on the next step:
Add a base controller:
public class M2aBaseController : Controller
{
public IDocumentSession DocumentSession { get; set; }
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.IsChildAction)
return;
this.DocumentSession = RavenDbConfig.Store.OpenSession();
base.OnActionExecuting(filterContext);
}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.IsChildAction)
return;
if (this.DocumentSession != null && filterContext.Exception == null)
this.DocumentSession.SaveChanges();
this.DocumentSession.Dispose();
base.OnActionExecuted(filterContext);
}
}
Basically, the previous M2aBaseController
will take care of the DocumentSession
and make sure it’s open before any controller action that inherits the base Controller
and disposed right after. It was suggested by Ayende, the co-founder of RavenDb
, on the RavenDb web site.
This is just great for simple applications, but when it comes to heavy stuff applications, I would move all the code in M2aBaseController
down to Data layer where it belongs. M2aBaseController
will be the base repository in Repository Pattern scenario.
Besides the design of your application and in which layer you choose to handle what, the value of using RavenDb
remains the same: simple to use, reliable and the client that comes with is the one who’s doing the magic behind the scenes.
To add an object to the data store and get back the data from it, your controller should inherit from the M2aBaseController
. Then to create a document, add a create
action method as follows:
[HttpPost]
public ActionResult Create()
{
var schedule = new Schedule
{
Name=" Tirezzaf",
Description = "Ad asegh ar tmurt iyi d-jjan imezwura",
Departure= DateTime.Today.AddDays(2)
};
this.DocumentSession.Store(schedule);
return RedirectToAction("Index");
}
Schedule
is a business object and all what I need to do to save it is this.DocumentSession.Store(schedule);
And my Schedule
is now in the data store (in database as relational databases folks would argue). It’s just so easy.
To get back the documents and send them to a view for display, add to your Index
method (or another one):
var schedules = this.DocumentSession.Query<Schedule>().OrderByDescending
(i => i.Name).ToList();
As you noticed, it's just a regular Linq stuff to order or search for specific document. I think you get the idea, so you can just play with it a little bit to get used to it.
Of course, there is a lot of stuff you can discover about RavenDb, as indexes, sharding and how to manage your store via a browser, etc. The server version is also worth a try. A lot of information, how-tos and other documentation are available on RavenDb
web site. Ayende answers questions out there.