In my previous post in this series on NoSQL Databases, I showed how RavenDB embedded could be added to an existing ASP.NET MVC 3 application using NuGet and how it can be configured to use a folder in the App_Data folder. 

In this blog I will add the code needed for my TaskController class to use RavenDB to store its data.

Everything in RavenDB goes through an instance of IDocumentStore.  There are two classes in the RavenDB API which implement this interface DocumentStore and EmbeddedDocumentStore.  We will be using the latter.

We can create a RavenDocumentStore class which is like the DataContext or DbContext classes in Entity Framework.

Listing 1: The RavenDocumentStore Class
public class RavenDocumentStore
{
    private static IDocumentStore instance;

    public static IDocumentStore Instance
    {
        get
        {
            if (instance == null)
                throw new InvalidOperationException("…");
            return instance;
        }
    }

    public static IDocumentStore Initialize()
    {
        instance = new EmbeddableDocumentStore
                        {
                            ConnectionStringName = "RavenDB"
                        };
        instance.Conventions.IdentityPartsSeparator = "-";
        instance.Initialize();
        return instance;
    }
}
 

The static property Instance ensures that we only have one instance of the DocumentStore, and the Initialize method can be called in Application_Start.  We could have created the instance inside the Instance getter, but that would not be thread-safe.

Listing 2: The Application Start method
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RavenDocumentStore.Initialize();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}
 

We are going to need an IDocumentSession to do the work.  We could create a new IDocumentSession instance at the beginning of each Action method and then dispose of it at the end of each method.  But MVC has two very convenient hooks to do this – OnActionExecuting and OnActionExecuted.  These methods are executed before and after each action method, so we will create a new IDocumentSession in OnActionExecuting and dispose of it in On ActionExecuted.  To do this we will create  a BaseRavenController class to act as a base class for our TaskController (Listing 3).

Listing 3: The BasenRavenController class
public class BaseRavenController : Controller
{
    public IDocumentSession RavenSession { get; set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        RavenSession = RavenDocumentStore.Instance.OpenSession();
        base.OnActionExecuting(filterContext);
    }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (RavenSession != null)
        {
            RavenSession.SaveChanges();
            RavenSession.Dispose();
        }
        base.OnActionExecuted(filterContext);
    }
}

Finally we can then modify each action method to use the RavenSession instead of the Entity Framework DbContext.  As an example the Index action (Listing 4) and the Edit actions (Listing 5) are shown.

Listing 4: The Index Action method
public ViewResult Index()
{
    var tasks = RavenSession.Query<Task>().ToList();
    return View(tasks);
}

 

Listing 5: The Edit Action methods
public ActionResult Edit(string id)
{
    Task task = RavenSession.Load<Task>(id);
    return View(task);
}

[HttpPost]
public ActionResult Edit(Task task)
{
    if (ModelState.IsValid)
    {
        RavenSession.Store(task);
        return RedirectToAction("Index");
    }
    return View(task);
}

That is basically it – although there is one last change that needs to be made.  RavenDB uses a “key” to identify each document.  By default, just like an Identity column in SQL Server, RavenDB will generate this key automatically – the default behaviour being to create a key of the form “tasks/1” – i.e. the plural of the object’s name followed by the default “/” separator and a hilo generated integer. 

The default separator can be changed and we did that in Listing 1 by setting the IdentityPartsSeparator  to a “-“, so that we didn’t interfere with the Url separator in our routes.  And since we now have a string “key” the Id property of our Task object (and all the Action method parameters) can be changed to a string.

Figure 1 and Figure 2 show the Tasks Application running in List and Edit mode.

Figure 1: The MyTasks MVC Application in List (Index) view
image

 

Figure 2: The MyTasks MVC Application in Edit view
image

So that’s it – its not very hard at all to start working with RavenDB.  The only challenge so far being that I cannot look into the Data Store in the same way that I can with the SQL Server tools in Visual Studio or SQL Management Studio.

However, this is not the end of this series of Blogs.  I will continue to explore NoSQL databases, in particular RavenDB.


Posted in: Data  Tags: , , ,

In my continuing series on NoSQL Databases I have been mainly describing some of the concepts behind NoSQL (and in particular Document) Databases.  In this post I will start to dive into some code.

As mentioned earlier I will be using RavenDB as this is a .NET friendly database.

In this first example lets create a simple ASP.NET MVC 3 Application that uses RavenDB as its data source.

I will start with a simple “My Tasks” Application which I created by using the Internet Application template in ASP.NET MVC 3.  Next I created a simple Task model class (Listing 1).

Listing 1: The Task class
    public class Task
    {
        public int TaskId { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public bool IsComplete { get; set; }
    }
 

I then used the Scaffolding available in ASP.NET MVC 3 to create a TaskController (Figure 1), as well as the Entity Framework DataContext class and all the Razor Views necessary for CRUD operations.

Figure 1: Scaffold a new TaskController class
image

And finally I created a SQL Server Compact Edition Database to store the data and a Tasks table with columns that matched the names and types of the Task class’s properties.

To prove that everything was wired up correctly I browsed to the application and added some data (Figure 2).

Figure 2: A List of Tasks
image

But the goal of this application is to use RavenDB as the database, not to create an EF Code First/SQL CE application.

As I mentioned in the 3rd post in this series, RavenDB can be configured in three different ways.  I am going to use the embedded mode.  Luckily, RavenDB is available as a NuGet package.  To add a NuGet package to a Visual Studio project we can right-click on the References folder (Figure 3).

Figure 3: Add a new Nuget package
image

and select “Manage NuGet Packages”.  In the Package Manager window enter Raven  in the search box and install the RavenDB (Embedded) package (Figure 4).

Figure 4: Install RavenDB using NuGet
image

The installation adds quite a few assemblies to the bin folder.

Next we need to configure Raven, so we will create a Folder in the App_Data folder call “Database” (Figure 5),

Figure 5: Create a new Database Folder for the RavenDB database
image

and we will modify the connection string that RavenDB added to the web.config to point to the folder we just created.

Listing 2: Update connection string in web.config
  <connectionStrings>
    <add name="RavenDB " connectionString="DataDir = ~\App_Data\Database" />
  </connectionStrings>
 

So now we are all set up ready to convert our application to use RavenDB, and in the next post I will show how to hook up the existing TaskController class, so we can store our tasks in an embedded RavenDB database instead of a SQL Compact database.


Posted in: Data , ASP.NET  Tags: , , ,

As my frequent readers would have noticed already, I have been diving into NoSQL databases recently – in particular Document Databases.  But why do we need NoSQL databases in the first place.  Surely the relational databases we have been using work fine – in fact they work very well in most situations. 

The problem with them is they don’t always scale very well – and when I mean scale, I mean scale really big – across multiple nodes in a cluster.  I alluded to this in the first post in this series, but as an aside I have decided to explore why in further detail in this post.

It all comes down to the CAP (or Consistency, Availability and Partition Tolerance) Theorem.  This theorem states that when working with distributed systems you can only achieve two of the three goals, so you need to decide what is important to you.

If Consistency is most important then you would choose a relational database which excels at Consistency.  Examples of when Consistency would be important are in financial systems or nuclear power stations, where it is critical that every piece of data is accounted for. 

However, in most cases, “eventual consistency” is all that matters.  For example in a content management system if a Page Editor updates a page it is not critical that every user sees that change immediately, as long as at some time in the near future (seconds or minutes) the update is visible. 

In most applications it is more important that some version of the data is available at all times – i.e. the A or Availability of the CAP theorem.  In systems that focus on Availability, server uptime is more important than the exact version of the data.

Finally, the P or Partition Tolerance defines the ability of the data to be distributed (partitioned) across multiple servers – this allows for hugely scalable systems, like Google or Facebook.

Document Databases (as with most NoSQL databases) excel at the A (Availability) and P (Partition Tolerance) corners of the triad and so are less good at Consistency - eventual consistency is good enough. 

Thus Document Databases are fast and can scale, but would never be used to run a financial system or a nuclear power station.


 Search Blog

 Calendar

«  February 2012  »
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
2728291234
567891011
View posts in large calendar

 Tags

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012 Thoughts from the Wet Coast