Getting started with RavenDB in an ASP.NET MVC application

RavenDB is one of the newer document type databases that is conceptually comparable to MongoDB or CouchDB. One of the nice thing about RavenDB, at least for a .NET developer, is that is has been developed with .NET in mind from the start. And this makes it really easy to get started with. In fact it is so easy to get started with that it surprises me that not everyone is using it.

One of the things that attract me to document databases like RavenDB is the fact that they are really fast and schema free. This means that I don’t have to worry about creating database tables or those administrator like tasks. Instead I just create my C# classes and store them as documents in the database. Make a change to my class, no problem it just keeps on working.

Creating a real simple ASP.NET MVC application using RavenDB

A quick demo will show just how easy it is to get started. I am starting with a standard ASP.NET MVC 3 application here. In order to get the RavenDB client and server packages I use NuGet to install them using the following two commands in the NuGet Package Manager Console:

 1: Install-Package RavenDB.Client

 2: Install-Package RavenDB.Server

The RavenDB Server

The RavenDB.Server package installs the server bit. There are other ways of doing things but for now lets do the simplest and just navigate to the Raven.Server.Exe and start it.

image

This will start the server running and by default it will listen on for HTTP traffic on port 8080. The server console will display all command that execute helping with debugging potential issues.

image

The RavenDB Client

The RavenDB.Client NuGet package installed the normal way into our project and added some references to the RavenDB client libraries. In order to use RavenDB in our C# code we first need to create a DocumentStore object. This is an object that only needs to be created once and can be cached for the duration of the application live time. One nice and simple way of doing this is by adding the following bit of code to the Global.asax and calling this from the Application_Start() function.

 1: public static IDocumentStore RavenDBDocumentStore { get; private set; }

 2:  

 3: private static void CreateRavenDBDocumentStore()

 4: {

 5:     RavenDBDocumentStore = new DocumentStore

 6:     {

 7:         ConnectionStringName = "ravenDB"

 8:     }.Initialize();

 9: }

In this case I am pointing to a connection string in the web.config so lets make sure that is added. Basically I am pointing this to HTTP port 8080 on the local machine which is the server we started before this.

 1: <connectionStrings>

 2:   <add name="DefaultConnection"

 3:        providerName="System.Data.SqlClient"

 4:        connectionString="Data Source=(LocalDb)v11.0;Initial Catalog=aspnet-RavenMvc-20121125145005;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnet-RavenMvc-20121125145005.mdf" />

 5:   <add name="ravenDB"

 6:        connectionString="Url=http://localhost:8080"/>

 7: </connectionStrings>

In order to store or retrieve data we need to use the DocumentStore to open a session. Most database interactions, and all standard ones, are done through a session object. This session object should be short lived, create one, do a few interactions with it and dispose of it. And when it comes to a few interactions RavenDB pushes you towards the right thing. Do to many database queries and you will see an InvalidOperationException with message “The maximum number of requests (30) allowed for this session has been reached.” informing you that you can do only 30 actions at the time. This might seems strange but RavenDB has a number of these defaults that lead developers towards making the right choices.

In this demo I am going to use a simple book application to show how simple it is to get started with RavenDB. The book class is pretty basic and looks like this;

 1: namespace RavenMvc.Models

 2: {

 3:     public class Book

 4:     {

 5:         public int Id { get; set; }

 6:         public string Title { get; set; }

 7:         public string Author { get; set; }

 8:     }

 9: }

A list of books application

Showing a lost of books is real simple. All I need is the following code:

 1: public class BooksController : Controller

 2: {

 3:     //

 4:     // GET: /Books/

 5:     public ActionResult Index()

 6:     {

 7:         using (var session = MvcApplication.RavenDBDocumentStore.OpenSession())

 8:         {

 9:             var books = session.Query<Book>().ToList();

 10:             return View(books);

 11:         }

 12:     }

 13: }

Just running this will work just fine. Note that I have not created any databases or tables. Instead RavenDB will just check to see of it knows about books and if so return them. In fact it will return the first 128 by default as that is another of those default to help developers make the right choice. The thing to note in the code is that I am using the DocumentStore to create a new session object, using the session to do a query and then disposing the session object again. This is the basic approach when using RavenDB that you keep on repeating.

image

Loading a single book

The session.Query<Book> returns an IQueryable object so you could just start do queries. However if you know the identity of the book it is faster to use the Load() function instead.

 1: //

 2: // GET: /Books/Details/5

 3: public ActionResult Details(int id)

 4: {

 5:     using (var session = MvcApplication.RavenDBDocumentStore.OpenSession())

 6:     {

 7:         var book = session.Load<Book>(id);

 8:         return View(book);

 9:     }

 10: }

Storing a new book in the database

Adding  a new book isn’t much harder. In this case we do need to make sure we call SaveChanges() on the session as that commits the changes to the database. If we don’t do this they will be lost when the session is disposed.

 1: //

 2:         // POST: /Books/Create

 3:         [HttpPost]

 4:         public ActionResult Create(Book book)

 5:         {

 6:             if (ModelState.IsValid)

 7:             {

 8:                 using (var session = MvcApplication.RavenDBDocumentStore.OpenSession())

 9:                 {

 10:                     session.Store(book);

 11:                     session.SaveChanges();

 12:                 }

 13:  

 14:                 return RedirectToAction("Index");

 15:             }

 16:  

 17:             return View(book);

 18:         }

The important thing to remember is we haven’t defined any schema in the database for this to work. Instead RavenDB just saves the object. In fact it converts it to a JSON format first and stores it that way. The data is easy to see. Part of the RavenDB.Server package is a Silverlight client that lets you manage the server and inspect, or even change, the data. After adding a few books this looks like this:

image

If we edit a document we can see the actual JSON representation of the book. Note that the associated metadata contains the CLR type so RavenDB knows how to handle your query and deserialize the data.

image

Updating and deleting the books is just as simple.

 1: //

 2: // POST: /Books/Edit/5

 3: [HttpPost]

 4: public ActionResult Edit(int id, Book updated)

 5: {

 6:     if (ModelState.IsValid)

 7:     {

 8:         using (var session = MvcApplication.RavenDBDocumentStore.OpenSession())

 9:         {

 10:             var book = session.Load<Book>(id);

 11:             book.Title = updated.Title;

 12:             book.Author = updated.Author;

 13:             session.Store(book);

 14:             session.SaveChanges();

 15:         }

 16:  

 17:         return RedirectToAction("Index");

 18:     }

 19:  

 20:     return View(updated);

 21: }

 22:  

 23: //

 24: // POST: /Books/Delete/5

 25: [HttpPost]

 26: public ActionResult Delete(int id, Book deleted)

 27: {

 28:     using (var session = MvcApplication.RavenDBDocumentStore.OpenSession())

 29:     {

 30:         var book = session.Load<Book>(id);

 31:         session.Delete(book);

 32:         session.SaveChanges();

 33:     }

 34:  

 35:     return RedirectToAction("Index");

 36: }

That is all there is to it to get started. With a bit of simple C# code I can store books and I never needed to worry about the database side of things. Sweet :-)


Leave a comment