RavenDB CRUD – How To

I always wondered how easy it would be to do a RavenDB CRUD (Create, Read, Update, Delete) example, so lets create a simple MVC application which we can use to create, read, update and delete.

The following is some very basic code and yes you guessed it not for production but more of a quick sample to get you on your way with RavenDB and adding, editing and deleting documents.

We shall use a product model as our basis for the demo application – let’s get started.

  1. Create a blank MVC solution to begin with
  2. Using Nuget add in the Nuget package called RavenDB
  3. Lets setup RavenDB as we require within the global.asax.cs file as below:-
    [sourcecode language=”csharp”] protected void Application_Start()
    {
    AreaRegistration.RegisterAllAreas();

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

    Store = new DocumentStore { ConnectionStringName = "RavenDB", DefaultDatabase = "Products" };
    Store.Initialize();
    }
    [/sourcecode] Note:- I have added in a DefaultDatabase config value above which means I have created a new Products Raven Database within the RavenDB Management Studio called Products, if you don’t do this and just want to use the default database then remove the part DefaultDatabase = “Products”

  4. Add a class into the Models folder called Product as below:-
    [sourcecode language=”csharp”] public class Product
    {
    public string Id { get; set; }
    public string CategoryId { get; set; }
    public string SupplierId { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }
    public decimal StandardCost { get; set; }
    public decimal ListPrice { get; set; }
    public int UnitsOnStock { get; set; }
    public int UnitsOnOrder { get; set; }
    public bool Discontinued { get; set; }
    }
    [/sourcecode]
  5. Now that we have our Model, let’s go ahead and add in a couple of controllers. We will use a base controller when working with our RavenDB project so firstly create a RavenDB Controller, to do this right-click on controllers folder and then select Add then choose Controller, select Empty Controller.
  6. Paste this code into your RavenController:-
    [sourcecode language=”csharp”] public class RavenController : Controller
    {
    public IDocumentSession _session { get; private set; }

    public const int DefaultPage = 1;
    public const int PageSize = 10;

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
    if (filterContext.IsChildAction)
    return;
    _session = MvcApplication.Store.OpenSession();
    base.OnActionExecuting(filterContext);
    }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
    if (filterContext.IsChildAction)
    return;

    using (_session)
    {
    if (filterContext.Exception != null)
    return;

    if (_session != null)
    _session.SaveChanges();
    }
    }

    protected int CurrentPage
    {
    get
    {
    var s = Request.QueryString["page"];
    int result;
    if (int.TryParse(s, out result))
    return Math.Max(DefaultPage, result);
    return DefaultPage;
    }
    }
    }
    [/sourcecode]

  7. Lets now add a ProductController and this time choose, Controller with empty read/write actions as below:-
    ProductController
  8. We will start off by adding in some code which I have already written for the methods which we will use on the Products Controller, add them into your code:-
    [sourcecode language=”csharp”] public class ProductController : RavenController
    {
    //
    // GET: /Product/

    public ActionResult Index()
    {
    var model = _session.Query<Product>()
    .Paging(CurrentPage, DefaultPage, PageSize)
    .ToList();

    Mapper.Map<List<Product>, List<ProductViewModel>>(model);

    return View(model);
    }

    //
    // GET: /Product/Details/5

    public ActionResult Details(string id)
    {
    var model = _session.Load<Product>(id);
    return View(model);
    }

    //
    // GET: /Product/Create

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

    //
    // POST: /Product/Create

    [HttpPost] public ActionResult Create(Product product)
    {
    try
    {
    _session.Store(product);
    return RedirectToAction("Index");
    }
    catch
    {
    return View();
    }
    }

    //
    // GET: /Product/Edit/5

    public ActionResult Edit(string id)
    {
    var model = _session.Load<Product>(id);
    return View(model);
    }

    //
    // POST: /Product/Edit/5

    [HttpPost] public ActionResult Edit(Product product)
    {
    try
    {
    _session.Store(product);
    return RedirectToAction("Index");
    }
    catch
    {
    return View();
    }
    }

    //
    // GET: /Product/Delete/5

    public ActionResult Delete(string id)
    {
    var model = _session.Load<Product>(id);
    return View(model);
    }

    //
    // POST: /Product/Delete/5

    [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(string id)
    {
    try
    {
    _session.Advanced.DatabaseCommands.Delete(id, null);
    return RedirectToAction("Index");
    }
    catch
    {
    return View();
    }
    }

    public ActionResult StoreSomeProductInDatabase()
    {
    var product = new Product
    {
    Name = "Product Name",
    CategoryId = "category/1024",
    SupplierId = "supplier/16",
    Code = "H11050",
    StandardCost = 250,
    ListPrice = 189
    };

    _session.Store(product);
    _session.SaveChanges();

    //return Content(product.Id);
    return RedirectToAction("Index");
    }

    public ActionResult InsertSomeMoreProducts()
    {
    for (int i = 0; i < 50; i++)
    {
    var product = new Product
    {
    Name = "Product Name " + i,
    CategoryId = "category/1024",
    SupplierId = "supplier/16",
    Code = "H11050" + i,
    StandardCost = 250 + (i*10),
    ListPrice = 189 + (i*10),
    };
    _session.Store(product);
    }

    _session.SaveChanges();

    //return Content("Products successfully created");
    return RedirectToAction("Index");
    }

    public ActionResult GetProduct(int id)
    {
    Product product = _session.Load<Product>(id);
    return Content(product.Name);
    }

    public ActionResult LoadAndUpdateProduct()
    {
    Product product = _session.Load<Product>("products/5");
    product.ListPrice -= 10;
    _session.SaveChanges();
    return Content("Product 5 successfully updated");
    }

    public ActionResult DeleteProduct(int id)
    {
    Product product = _session.Load<Product>(id);
    if (product == null)
    return HttpNotFound("Product {0} does not exist");
    _session.Delete(product);
    _session.SaveChanges();
    return Content(string.Format("Product {0} successfully deleted", id));
    }

    /// <summary>
    /// Get all the products that are available for sale (discontinued equal to false) ordered by the product’s list price
    /// </summary>
    /// <returns></returns>
    public ActionResult GetDiscontinuedProducts()
    {
    var products = from product in _session.Query<Product>()
    where product.Discontinued == false
    orderby product.ListPrice
    select product;

    return View(products.ToList());
    }
    }
    [/sourcecode]

  9. Ok so above we added a lot of code but this is good as this is the entire product controller and will allow us to add/edit/delete new products into RavenDB.
  10. I also added in a couple of methods for creating some test data, and also a method for returning discontinued products, mainly to show how you can go about doing this.
  11. Some screen shots are below, note they show me using RavenDB Profiler and MiniProfiler:-

    Crud 1

    Crud 2

    Crud 3

The code for this article is up on github here.
For more on RavenDB have a look at my other RavenDB posts here.

Please leave a comment, ask a question, find a bug or anything like that please let me know.