Using A Document Database – RavenDB

By | December 22, 2011

RavenDB is a document database. The main difference between RavenDB and a relational database is, that RavenDB doesn’t support relation between the rows/entities/documents. A document contains structural data, which is stored in JSON format.

This is a quickstart into RavenDB:

Step 1 – Database:
Create a new database. This DB doesn’t contain any structure. It’s just a empty container.

Step 2 – Structure:
Define your entity/POCO/document structure in C#.
I created a company and a employee class. A company can contain multiple employees.

public class Company
{
     public string Id { get; set; }
     public string Type { get { return "company"; } }
     public string Name { get; set; }
     public string Region { get; set; }
     public IList Employees { get; set; }
}

public class Employee
{
    public enum ERole
    { 
        CEO,
        CFO,
        Developer
    }

    public string Id { get; set; }
    public string Type { get { return "employee"; } }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public ERole Role { get; set; }
}

Example -> Create new document:
Following code snippet creates a new document with one company and three employees.

using (var documentStore = new DocumentStore { Url = "http://myurl:8080/" })
{
    documentStore.Initialize();

    using (var session = documentStore.OpenSession("testDB"))
    {
        var company = new Company() { Id = "company/1", Name = "Tvd" };
        company.Employees = new List() 
            {
                new Employee() 
                { 
                    Id = "emp/1", 
                    Firstname = "Darko", 
                    Lastname = "Micic", 
                    Role = Employee.ERole.Developer 
                },
                new Employee() 
                { 
                    Id = "emp/2", 
                    Firstname = "Steve", 
                    Lastname = "Steven", 
                    Role = Employee.ERole.Developer 
                },
                        
                new Employee() 
                { 
                    Id = "emp/3", 
                    Firstname = "Max", 
                    Lastname = "Min", 
                    Role = Employee.ERole.CFO 
                },
            };
        session.Store(company);
        session.SaveChanges();
    }

The stored document is structured as shown here:

{
  "Type": "company",
  "Name": "Tvd",
  "Region": null,
  "Employees": [
    {
      "Id": "emp/1",
      "Type": "employee",
      "Firstname": "Darko",
      "Lastname": "Micic",
      "Role": "Developer"
    },
    {
      "Id": "emp/2",
      "Type": "employee",
      "Firstname": "Steve",
      "Lastname": "Steven",
      "Role": "Developer"
    },
    {
      "Id": "emp/3",
      "Type": "employee",
      "Firstname": "Max",
      "Lastname": "Min",
      "Role": "CFO"
    }
  ]
}

Example -> Read document:
Reading documents is quiet easy. Open a new session and run a query. (LINQ or with Lambda Expression).
This code here reads the company with the id “company/1” and updates the name.

using (var documentStore = new DocumentStore { Url = "http://myurl:8080/" })
{
    using (var session = documentStore.OpenSession("testDB"))
    {
        var company = session.Query().Where(x => x.Id == "company/1").FirstOrDefault();
        company.Name = "TVD";
        session.SaveChanges();
    }
}

Example -> Read childs out of a document:
As you can see in the examples above, the employee (child) isn’t stored in a seperate document. (In a relational database you will create
a table for company and one for employee.)
If you want to retrieve ONLY the employees out of a company document, you have to write following code:

using (var session = documentStore.OpenSession("testDB"))
{
    var emps = session.Query("Employees").Where(x => x.CompanyId == "company/1");
    foreach (var e in emps)
    {
        // do something
    }
}

This query excepts a result of type EmployeeResult. The parameter “Employees” is the name of a index, which is defined in the database.
The Employees index contains a match and a transform query.

Match LINQ:

from c in docs.Companies
select new { CompanyId = c.Id }

Transform LINQ:

from c in results
from e in c.Employees
select new { CompanyId = c.Id, Employee = e }

The class EmployeeResult contains the company id an the employee object. This structure corresponds the result of the transform query.

public class EmployeeResult
{
    public string CompanyId { get; set; }
    public Employee Employee { get; set; }
}

(I’m still not sure if there’s an easier way for retrieving the “childs”/employees.)

Happy coding 😉

  • Brahim Boulkriat

    Hi Darko , i’am a Tunisian software ingennering student and i’am builiding a social network with amazing and exiting features and ideas for the next Microsoft imagine cup .I will implement it using Asp.net mvc 4 , Web API , SignalR and KnockoutJs.Can you help me in the technologie and architecture decisions and in the development ?
    Thanks.

  • Brahim Boulkriat

    I want to use RavenDB too for data storage

  • dmicic

    Hi Brahim. Sounds interesting. 🙂 I’m glad if I can help you. Do you have already a pre version online somewhere? would be cool to have a short look at it. 🙂