Infragistics ASP.NET controls

Introducing RavenDB: Welcome to the world of NoSQL

Relational Databases

If you are a software developer then you probably have some sort of experience with a traditional RDBMS (Relational Database Management System).  SQL or structured query language is the language that you use to retrieve data from a SQL based database system.  SQL based database systems are based on relational algebra.  You initiate queries to retrieve sets or intersections of data.  These databases are defined by their schema.  The schema defines tables, columns, relationships, constraints, and keys.  SQL databases have been around for a long time and they aren't going anywhere anytime soon.  There is a time and place to use this type of system.  Typical uses include Data warehousing, data reporting, and application data storage.  

Complexities of SQL based database systems

With SQL based database systems you often need a database administrator to facilitate maintenance on the server.  In a clustered database environment, concurrency can become an issue when you need to combine data from multiple database systems into one central database.  Issues of replication or redundancy and back up disaster recovery requires an administrator that fully understands the way that SQL schema's and programming work.

SQL to objects and objects to SQL

When programming in SQL based databases, there is a fundamental challenge of pulling data from a database using SQL and transforming the set based results into an object's properties.  The same difficulties must be resolved when saving object properties back to the SQL database.  For the past 10+ years it has been up to the developer to write custom code to handle these issues.  Recently, ORM systems have assisted developers with this issue.  The schema still requires the developer to map object properties to database columns.  If the schema changes, you have to change database stored procedures, functions, as well as application code that deals with selecting and inserting and updating data.  The functions that facilitate relational databases create difficulties that must be solved to use the systems effectively.

Repository pattern

The repository pattern exists to provide a way to retrieve data from a routine that provides a layer of abstraction between the call and the underlying database server.  This is usually implemented by some interfaces and specific repository classes.  This adds to the amount of infrastructure boiler plate code that must be used in each application to simply retrieve data from an SQL database.

Ditching the schema

Recently there has been a lot of talk about NoSQL based databases.  When I first heard about this concept, I was very skeptical on how this would work.  I had been working with SQL for the past 10 years and it's what I've been used to.  I decided I would take a look at RavenDB to see what all the fuss was about.  RavenDB has changed my views on the issue.

There are times when you have no need to worry about the way that your data is stored.  There are some instances in which you have no need to generate reports on data or utilize relationships.  Some times you simply need the ability to store an object's state and retrieve it later for use in your application.  This illustrates a perfect time to utilize NoSQL and RavenDB.

Saving data the SQL way

To save data in a typical RDBMS, you must create a SQL INSERT or UPDATE statement and traverse the properties values of the object that you wish to save to the database.  If the schema ever changes, you must change all application code that saves or retrieves data from a database.

Setting up RavenDB Embedded 

You must start by adding RavenDB to your solution.  I did this by using the Nuget package manager.  There are 3 ways to run RavenDB.  You can run RavneDB as an HTTP service, a Windows service, or when using RavenDB in a .NET application, you can run the RavenDB embedded server which allows RavenDB to execute as an in process DLL service.  This requires no server to run.  You simply point to a folder on your file system to save the data.

Please note that when you save data to RavenDB, the objects are serialized to JSON for storage.  Here is a screen shot of how to get to the Nuget package manager.  Keep in mind that you want to add RavenDB once you have your solution open in Visual Studio.

 

Once you launch the package manager Search for RavenDB and choose the embedded server.

The nuget package manager will discover and download the other package dependencies like the RavenDB client and Database packages.

When you run RavenDB in Embedded mode, the DataDirectory property of the DocumentStore should be the directory that you wish to store the data saved to the database. Once you have a valid document store, you need to create a session to preform the save and query operations. The session object provides a way of saving and accessing data in the document store.  

Querying data in RavenDB

You can use Linq to query data from a RavenDB database.  Linq provides a strongly typed way of querying a RavenDB database by specifying object properties in the query.  

Here is a complete example of saving and querying a RavenDB database.

The example is a console application.  

The application is made up of a Customer class, a DataAccessLayer class, and the main program class.

The program will create an instance of the Customer class and save that object to the RavenDB database.  Next, the program will query the database to retrieve a Customer object with the ID of the object that was just saved.  The program will print the two Id's for comparison and await for the user to press a key to end the program.

Customer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RavenDBExample
{
    public class Customer
    {
        public Guid Id;
        public string CustomerName;
        public string CustomerAddress;
    }
}

DataAccessLayer.cs

using Raven.Client;
using Raven.Client.Embedded;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RavenDBExample
{
    public static class DataAccessLayer
    {
        private static EmbeddableDocumentStore _documentStore;

        public static void SaveCustomer(Customer customer)
        {
            if (_documentStore == null)
                CreateDocumentStore();

            using (IDocumentSession session = _documentStore.OpenSession())
            {
                // Operations against session
                session.Store(customer);

                // Flush those changes
                session.SaveChanges();
            }
        }

        private static void CreateDocumentStore()
        {
            _documentStore = new EmbeddableDocumentStore
            {
                DataDirectory = "Data"
            };

            if (_documentStore == null)
                throw new NullReferenceException("Error creating document store");

            _documentStore.Initialize();
        }

        public static Customer LoadCustomer(Guid guid)
        {
            if (_documentStore == null)
                CreateDocumentStore();

            using (IDocumentSession session = _documentStore.OpenSession())
            {
                var customer = session.Query<Customer>().Where(cust => (cust.Id == guid)).FirstOrDefault();
                return customer;
            }

            return null;
        }
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RavenDBExample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var customerToSave = new Customer { Id = Guid.NewGuid(), CustomerName = "John Doe", 
                CustomerAddress = "1234 Mystery Street, Somewhere, California, 55555" };

            DataAccessLayer.SaveCustomer(customerToSave);

            var existingCustomer = DataAccessLayer.LoadCustomer(customerToSave.Id);

            if (existingCustomer == null)
                throw new NullReferenceException("Unable to load the customer");

            Console.WriteLine("The CustomerID that was saved = {0} .  The CustomerID loaded = {1} .", customerToSave.Id, existingCustomer.Id);
            Console.ReadKey();
        }
    }
}

 

There are other features as well such as change tracking. Change tracking occurs when you retrieve an object from the database, all changes to that object are tracked. You can later call save changes on the session to save the changes to the object. This concludes a high level discussion of NoSQL vs SQL database systems and specifically how to use the RavenDB document database. As you can see, if you have no need to apply relational algebra or care about the schema of a database then NoSQL based databases like RavenDB can be extremely useful.

Download the full application example below

RavenDBExample.zip (2.42 mb)

 

kick it on DotNetKicks.com

 

 

 



Comments (1) -

pankaj90
pankaj90
11/24/2012 6:54:12 AM #

Really Helpful code...Thank You....

http://price-specifications.com/

Pingbacks and trackbacks (2)+

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

About the author

My name is Buddy James.  I'm a Microsoft Certified Solutions Developer from the Nashville, TN area.  I'm a Software Engineer, an author, a blogger (http://www.refactorthis.net), a mentor, a thought leader, a technologist, a data scientist, and a husband.  I enjoy working with design patterns, data mining, c#, WPF, Silverlight, WinRT, XAML, ASP.NET, python, CouchDB, RavenDB, Hadoop, Android(MonoDroid), iOS (MonoTouch), and Machine Learning. I love technology and I love to develop software, collect data, analyze the data, and learn from the data.  When I'm not coding,  I'm determined to make a difference in the world by using data and machine learning techniques. (follow me at @budbjames).  

Related links

Month List