Agile Zone is brought to you in partnership with:

Michael Ceranski is a .NET developer from Buffalo NY. He has been writing code for over 10 years starting with Borland Delphi and later migrating to the .NET stack. Michael enjoys blogging about .NET, MVC and jQuery. When Michael is not consulting he spends his time working on WeBlog, a next generation blogging platform written in ASP.NET MVC 2. Michael is a DZone MVB and is not an employee of DZone and has posted 34 posts at DZone. You can read more from them at their website. View Full User Profile

Using RavenDB with ASP.NET MVC

11.08.2010
| 7118 views |
  • submit to reddit
Traditionally when you think about a database you think of tables, views, indexes and stored procedures. If you have made a career out of developing database centric applications like I have, then chances are that you have spent a great deal of time dealing with issues around referential integrity, normalization and performance.

Unless you have been living underneath a rock, then you have probably heard of the newest database trend named NoSQL. NoSQL refers to non relational document databases that help address issues like performance and scalability which are often hard to achieve when using traditional database systems such as SQL or Oracle.  NoSQL replaces the old “scale up” mantra of database management  with a new one: “scale out.” Instead of adding bigger servers to handle more data load, a NoSQL database allows a company to distribute the load across multiple hosts as the load increases. In case you are wondering many successful companies such as Amazon, the BBC, Facebook and Google already rely on NoSQL DBs for day to day operations.

If you do a quick search on the web you will discover that there are many document databases to choose from. Some of the most popular options today are MongoDB, CouchDB and RavenDB. For whatever reason I was attracted to RavenDB because I knew it would seamlessly integrate with the .NET/windows platform. As always, the best way to learn something is to jump in head first. So the following article is a step-by-step tutorial on how I built an MVC 2 web app using RavenDB as the backend.

 

Installing RavenDB

  • Download the latest bits from the RavenDB website. In order to keep things simple extract the files to C:\Raven
  • In my example I configured RavenDB as an IIS application. Here are the steps which I have taken directly from the RavenDB website:
    • Extract the distribution zip.
    • In IIS Manager, create a new Web Site and point its physical path to the "/Web" folder in the extracted folder.
    • Set the Application Pool to "ASP.Net v4.0" (or create a new Application Pool set to .NET 4.0 Integrated Pipeline)
    • Set port and host, if you need them.
    • Make sure that the user you set for the site has write access to the physical database location.
  • Finally, make sure that you have read/write access to the “c:\Raven\Web\Data folder”.

Once everything is configured you should be able to open a browser and view the RavenDB console:

image

Using RavenDB with ASP.NET MVC

After you create your ASP.NET MVC web app, the first thing you need to do is add a reference to the C:\Raven\Client\Raven.Client.Lightweight.dll assembly.

Second, you need to initialize the client. According to the documentation the DocumentStore object should only be created once per application. So I setup my document store in the Application_Start event of my MVC application:

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterRoutes(RouteTable.Routes);

var documentStore = new Raven.Client.Document.DocumentStore { Url = "http://localhost:8080" };
documentStore.Initialize();
Application["DocumentStore"] = documentStore;

ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
}

At this point you have an initialized client and you could start accessing the data. However, I decided to wrap my calls in a repository class. My repository class implements an interface so I can easily create a “fake” repository for unit testing purposes.  As a good practice, I typically create a base controller which takes an IRepository object as a parameter. This is a simple form of Dependency Injection that comes in handy when creating unit tests later on. Anyways, the repository code that I came up with is very simple and straightforward. The Raven API utilizes LINQ so as a .NET developer you should feel right at home. As you will see below, the constructor of the RavenRepository class takes a DocumentStore which was created during the Application_Start event. Here is the code:

public class RavenRepository : IRepository
{
private DocumentStore _store;
private IDocumentSession _session;

public RavenRepository(DocumentStore store)
{
_store = store;
_session = _store.OpenSession();
}

public T SingleOrDefault<T>(Func<T, bool> predicate) where T : IModel
{
return _session.Query<T>().SingleOrDefault(predicate);
}

public IEnumerable<T> All<T>() where T : IModel
{
return _session.Query<T>();
}

public void Add<T>(T item) where T : IModel
{
_session.Store(item);
}

public void Delete<T>(T item) where T : IModel
{
_session.Delete(item);
}

public void Save()
{
_session.SaveChanges();
}
}

Now, that the repository is created we need to create some models to use with it. Here is a simple Person class. I also added a few data annotations to make validation and formatting easier in MVC.

public class Person : IModel
{
public string Id { get; set; }

[DisplayName("First Name")]
[Required(ErrorMessage="*")]
public string FirstName { get; set; }

[DisplayName("Last Name")]
[Required(ErrorMessage = "*")]
public string LastName { get; set; }

[Required(ErrorMessage = "*")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
}

In order to understand how the repository works, lets take a look at the Create and Edit methods that I created in the PersonController. The create action is very simple, you instantiate a new person, add it to the repository and then save your changes:

public ActionResult Create()
{
var model = new PersonViewModel();
return View(model);
}

[HttpPost]
public ActionResult Create( PersonViewModel input )
{
var person = new Person
{
FirstName = input.Person.FirstName,
LastName = input.Person.LastName,
Email = input.Person.Email
};

_repository.Add(person);
_repository.Save();
TempData["Message"] = "Person created successfully";
return RedirectToAction("Index");
}

Editing is just as easy, you retrieve the record from the repository, update the properties and save:

public ActionResult Edit(string id)
{
var model = new PersonViewModel(_repository,id);

if (model.Person == null) return View("NotFound");

return View(model);
}

[HttpPost]
public ActionResult Edit(string id, PersonViewModel input)
{
var person = _repository.SingleOrDefault<Person>(x => x.Id == id);
person.FirstName = input.Person.FirstName;
person.LastName = input.Person.LastName;
person.Email = input.Person.Email;
_repository.Save();

TempData["Message"] = "Person updated successfully";
return RedirectToAction("Index");
}

Conclusion

Document databases are extremely easy to use, setup and develop against. The fact that you can create an object and stuff it into the database without having to fool around with an object to table mapping is absolutely fantastic! The demo project is attached.

RavenDbDemo.zip (114.69 kb)

References
Published at DZone with permission of Michael Ceranski, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Emma Watson replied on Fri, 2012/03/30 - 5:01am

Is there any special reason you are starting a new session in every repository. How do you handle the case when your request spans multiple repositories?

JDBC

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.