NoSQL with RavenDB
RavenDB is the latest addition to the NoSQL and document database world. RavenDB is an Open Source (with a commercial option) document database for the .NET/Windows platform developed by Ayende Rahien. Raven stores schema-less JSON documents, allow you to define indexes using Linq queries and focus on low latency and high performance. RavenDB is .NET focused document database which comes with a fully functional .NET client API and supports LINQ. RavenDB comes with two components, a server and a client API. RavenDB is a REST based system, so you can write your own HTTP cleint API. As a .NET developer, RavenDB is becoming my favorite document database. Unlike other document databases, RavenDB is supports transactions using System.Transactions. Also it's supports both embedded and server mode of database. You can access RavenDB site at http://ravendb.netA demo App with ASP.NET MVC
Let's create a simple demo app with RavenDB and ASP.NET MVC. To work with RavenDB, do the following steps.
- Go to http://ravendb.net/download and download the latest build.
- Unzip the downloaded file.
- Go to the /Server directory and run the RavenDB.exe. This will start the RavenDB server listening on localhost:8080
You can change the port of RavenDB by modifying the "Raven/Port" appSetting value in the RavenDB.exe.config file.
When running the RavenDB, it will automatically create a database in the /Data directory. You can change the directory name data by modifying "Raven/DataDirt" appSetting value in the RavenDB.exe.config file.
RavenDB provides a browser based admin tool. When the Raven server is running, You can be access the browser based admin tool and view and edit documents and index using your browser admin tool. The web admin tool available at http://localhost:8080
The below is the some screen shots of web admin tool
Working with ASP.NET MVC
To working with RavenDB in our demo ASP.NET MVC application, do the following steps
Step 1 - Add reference to Raven Cleint API
In our ASP.NET MVC application, Add a reference to the Raven.Client.Lightweight.dll from the Client directory.
Step 2 - Create DocumentStore
The document store would be created once per application. Let's create a DocumentStore on application start-up in the Global.asax.cs.
documentStore = new
DocumentStore { Url = "http://localhost:8080/" };
documentStore.Initialise();
The above code will create a Raven DB document store and will be listening the server locahost at port 8080
Step 3 - Create DocumentSession on BeginRequest
Let's create a DocumentSession on BeginRequest event in the Global.asax.cs. We are using the document session for every unit of work. In our demo app, every HTTP request would be a single Unit of Work (UoW).
BeginRequest += (sender, args) =>
HttpContext.Current.Items[RavenSessionKey]
= documentStore.OpenSession();
Step 4 - Destroy the DocumentSession on EndRequest
EndRequest += (o, eventArgs) =>
{
var
disposable = HttpContext.Current.Items[RavenSessionKey]
as IDisposable;
if
(disposable != null)
disposable.Dispose();
};
At the end of HTTP request, we are destroying the DocumentSession object.
The below code block shown all the code in the Global.asax.cs
private const string
RavenSessionKey = "RavenMVC.Session";
private static DocumentStore documentStore;
protected void Application_Start()
{
//Create a
DocumentStore in Application_Start
//DocumentStore
should be created once per application and stored as a singleton.
documentStore = new
DocumentStore { Url = "http://localhost:8080/" };
documentStore.Initialise();
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
//DI using Unity 2.0
ConfigureUnity();
}
public
MvcApplication()
{
//Create a
DocumentSession on BeginRequest
//create a document
session for every unit of work
BeginRequest += (sender, args) =>
HttpContext.Current.Items[RavenSessionKey]
= documentStore.OpenSession();
//Destroy the
DocumentSession on EndRequest
EndRequest += (o, eventArgs) =>
{
var disposable
= HttpContext.Current.Items[RavenSessionKey]
as IDisposable;
if (disposable
!= null)
disposable.Dispose();
};
}
//Getting the
current DocumentSession
public static IDocumentSession CurrentSession
{
get { return (IDocumentSession)HttpContext.Current.Items[RavenSessionKey];
}
}
We have setup all necessary code in the Global.asax.cs for working with RavenDB. For our demo app,
Let’s write a domain class
public class Category
{
public string Id { get;
set; }
[Required(ErrorMessage
= "Name Required")]
[StringLength(25,
ErrorMessage = "Must be less
than 25 characters")]
public string Name { get;
set;}
public string Description { get; set; }
}
We have created simple domain entity Category. Let's create repository class for performing CRUD operations against our domain entity Category.
public interface ICategoryRepository
{
Category
Load(string id);
IEnumerable<Category> GetCategories();
void Save(Category category);
void
Delete(string id);
}
public class CategoryRepository : ICategoryRepository
{
private IDocumentSession session;
public
CategoryRepository(IDocumentSession
session)
{
this.session
= session;
}
//Load category based on Id
public Category Load(string id)
{
return
session.Load<Category>(id);
}
//Get all
categories
public IEnumerable<Category> GetCategories()
{
var
categories= session.LuceneQuery<Category>()
.ToArray();
return
categories;
}
//Insert/Update
category
public void Save(Category category)
{
//store
category object into session
session.Store(category);
//save changes
session.SaveChanges();
}
//delete a
category
public void Delete(string
id)
{
var
category = Load(id);
session.Delete<Category>(category);
session.SaveChanges();
}
}
For every CRUD operations, we are taking the current document session object from HttpContext object.
session = MvcApplication.CurrentSession;
public static IDocumentSession CurrentSession
{
get { return (IDocumentSession)HttpContext.Current.Items[RavenSessionKey];
}
}
Retrieve Entities
The Load method get the single Category object based on the Id. RavenDB is working based on the REST principles and the Id would be like categories/1. The Id would be created by automatically when a new object is inserted to the document store. The REST uri categories/1 represents a single category object with Id representation of 1.
public Category Load(string id)
{
return
session.Load<Category>(id);
}
public IEnumerable<Category> GetCategories()
{
var
categories= session.LuceneQuery<Category>()
.WaitForNonStaleResults()
.ToArray();
return
categories;
}
For insert/Update a Category entity, we have created Save method in repository class. The Save mothod used for both insert and update category. We just need to store category object on the document session. The session.SaveChanges() will save the changes to document store. if the category is a new one, it will insert a new record and update the category object, if it is an existing category object.
public void Save(Category category)
{
//store category
object into session
session.Store(category);
//save changes
session.SaveChanges();
}
Delete Entity
In the Delete method, we call the document session's delete method and call the SaveChanges method to reflect changes in the document store.
public void Delete(string
id)
{
var
category = Load(id);
session.Delete<Category>(category);
session.SaveChanges();
}
Let’s create ASP.NET MVC controller and controller actions for handling CRUD operations for the domain class Category
public class CategoryController : Controller
{
private ICategoryRepository
categoyRepository;
//DI enabled
constructor
public
CategoryController(ICategoryRepository
categoyRepository)
{
this.categoyRepository
= categoyRepository;
}
public ActionResult Index()
{
var
categories = categoyRepository.GetCategories();
if
(categories == null)
return
RedirectToAction("Create");
return
View(categories);
}
[HttpGet]
public ActionResult Edit(string id)
{
var
category = categoyRepository.Load(id);
return
View("Save",category);
}
// GET:
/Category/Create
[HttpGet]
public ActionResult Create()
{
var
category = new Category();
return
View("Save", category);
}
[HttpPost]
public ActionResult Save(Category category)
{
if
(!ModelState.IsValid)
{
return
View("Save", category);
}
categoyRepository.Save(category);
return
RedirectToAction("Index");
}
[HttpPost]
public ActionResult Delete(string id)
{
categoyRepository.Delete(id);
var
categories = categoyRepository.GetCategories();
return
PartialView("CategoryList",
categories);
}
}
RavenDB is an awesome document database and many examples are available in codeplex.
No comments:
Post a Comment