Join NoSQL movement with RavenDB – Part 2 (Embedded, InMemory, and Management Studio)

This is the second post continued from the post,  Join NoSQL movement with RavenDB – Part 1.  Part 1 showed how easy it is to use RavenDB by embedding it into your console application using NuGet package manager.

This post, I will embed RavenDB to a normal Web Form application. After creating an empty web application, I just go to NuGet package manager like the previous post and install RavenDB Embedded.

imageimage

The screenshots above show the solution before and after RavenDB Embedded has been installed. Besides the required RavenDB libraries in References, you should see Raven.Studio.Xap, which I didn’t mention last time. The xap file allows me to use the Management Studio, which is a silverlight client that let you manage the data in a RavenDB server instance similar to a typical RDBMS client such as SQL Server Management Studio.

Next step is to continue building the application. I add a normal web form page. I will just put a normal GridView into the page with AutoGenerateDeleteButton set to true and a RowDeleting event handler. I also add a model class, Person (which I also use in the post, Adding Search to your C# Metro Style App ).

image

In the ListPeople.aspx code-behind page, I initialize the RavenDB instance as well as adding documents . I should have done this in Global.asax in non-demo application Winking smile.

    public partial class ListPeople : System.Web.UI.Page
    {
        static IDocumentStore ravenInstance;        

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack && ravenInstance == null){           
                // Initialize new RavenDB Memory Instance with EmbeddedHttpServer                
                ravenInstance = new EmbeddableDocumentStore { RunInMemory = true, UseEmbeddedHttpServer = true };                
                ravenInstance.Initialize();

                // Build Sample Data
                SamplePeople.BuildSamplePeople();
                
                using(var session = ravenInstance.OpenSession())
                {
                    foreach (var person in SamplePeople.People)
                    {
                        session.Store(person);
                    }
                    session.SaveChanges();
                }
                BindPeopleGrid(SamplePeople.People);
            }
        }        

        protected void PeopleGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
        {
            using (var session = ravenInstance.OpenSession())
            {
                // Get Deleting Id
                var personId = e.Values[0].ToString();   
                             
                // remove from RavenDB
                var person = session.Load<Person>(personId);
                session.Delete(person);
                session.SaveChanges();

                // rebind the data from RavenDB
                var people = session.Query<Person>();
                BindPeopleGrid(people);
            }            
        }

        void BindPeopleGrid(IEnumerable<Person> people)
        {
            PeopleGrid.DataSource = people;
            PeopleGrid.DataBind();
        }
    }

This time you might notice that I used different configuration options from the last time. I wanted to run RavenDB instance in memory (of course this means every time an instance is created, it will be an empty database, so utilize it carefully). Instead of setting ConnectionString, I put RunInMemory and UseEmbeddedHttpServer equal to true. The UseEmbeddedHttpServer option will allow me to access the RavenDB instance externally or through the REST API.

The other interesting in the code is the PeopleGrid_RowDeleting method which handles deleting event when a Delete button/link is clicked. Now let me just run the application.

image

I can also run the RavenDB Management Studio to see what documents we have in the current RavenDB instance. I can do this by hitting http://localhost:8080/ (RavenDB might use another port on your machine if 8080 is already used by another process), and I should see the nice Silverlight client. I can hover the document to see what my data looks like (i.e., JSON document). Please note that the value in Id property is automatically given by RavenDB when the person instance is being stored. For more information about different key generation options, please check http://ravendb.net/docs/theory/document-key-generation.

image

I clicked the Delete button/link in the GridView, and the document is deleted in RavenDB and on GridView.

image

image

In next RavenDB post (which I also promised last time), I will run RavenDB server in the console mode and show the RavenDB management studio which can be used to manage RavenDB server as well as see RavenDB in more detail. Enjoy coding!

Advertisements

Join NoSQL movement with RavenDB – Part 1

NoSQL (aka Not Only SQL which Martin Fowler does not actually like the term) database is a database that does not totally adhere to relational concept. Another important characteristic is that some NoSQL implementation may not give full ACID guarantee. However, because of their distributed architecture in mind, most NoSQL database are very scalable in contrast to a classic relational database which can suffer from scalability issue. I won’t discuss RDBMS vs. NoSQL here as they are both invented to solve problems and I believe that what you choose should depend on your problem.

Although I have heard about NoSQL Database for a while, I haven’t had a chance to try it yet until I learned about one of the NoSQL database, RavenDB in the Nashville .NET Usergroup meeting last week.

RavenDB is a document-oriented database which is one of NoSQL implementations. The main concept of document-oriented database is that it stores document with a key (i.e., key/value). A document encapsulates data and can be encoded by using JSON (in RavenDB case), XML, Microsoft Word, etc. Every document has unique key (i.e., id) that represents that document. RavenDB has been written entirely in .NET, stores data as schema-free JSON (i.e., key/value) and provide a RESTful API for interaction with the database. Any client that supports HTTP/JSON communication should be able to use RavenDB. For .NET client, RavenDB provides LINQ support as well.

RavenDB can be run in as a console application, Windows service, IIS application, or embedded with client.

In this post, I will introduce RavenDB in embedded mode which is the easiest way to get started as I don’t need to set up and run the RavenDB server separately. With the help of NuGet, I can install everything in just one click.

After I create a console application, I go to NuGet package manager, and look for RavenDB Embedded. The embedded package will install both RavenDB Client, Database, and Embedded into the console project.

image

image

After I agree and accept all license terms, in the Solution Explorer, there will be a whole bunch of references added into the project.

image

Before I start using embedded RavenDB, I will need to specify where the database should be located by specify connection string.  This is not so different from how other databases such as SQL Server or Oracle connection string is setup. I create a new folder called Database in my project just to separate database from the code, but I can have RavenDB use any location to which my application has access.

image

<connectionStrings>
   <add name="RavenDB" connectionString="DataDir = .\Database" />
</connectionStrings>

In the code, I start by creating a DocumentStore instance which is thread-safe. However, DocumentStore is not cheap to create (similar to SessionFactory in NHibernate), the instance should be created once per database and application. Although the sample code is using ConntectionStringName, I can also use DataDictionary to specify the location directly in my code.

 using (var docStore = new EmbeddableDocumentStore { ConnectionStringName = "RavenDB" }.Initialize()) 

After I have a DocumentStore instance, then I can get a session from it (very similar to Session in NHibernate as well). The full sample code below just show how I can create a new document (i.e., Person instances), store them to RavenDB and query them later using LINQ.

class Program
    {
        static void Main(string[] args)
        {
            using (var docStore =  new EmbeddableDocumentStore 
                { 
                    ConnectionStringName = "RavenDB" 
                }
                .Initialize())
            {
                using (var session = docStore.OpenSession())
                {
                    // add new person
                    var p = new Person { LastName = "Fuchsia", FirstName = "Cyan" };
                    session.Store(p);
                    
                    // Id is generated by RavenDB
                    Console.WriteLine("{0} generated by RavenDB"
                        , session.Advanced.GetDocumentId(p));
                    session.SaveChanges();

                    #region Add more people
                    session.Store(new Person { LastName = "Hanselman"
                        , FirstName = "Scott" });
                    session.Store( new Person { LastName = "Rahien"
                        , FirstName = "Ayende" });
                    session.Store( new Person { LastName = "Sinofsky"
                        , FirstName = "Steven" });
                    session.Store( new Person { LastName = "The Gu"
                        , FirstName = "Scott" });
                    session.SaveChanges();                    
                    #endregion
                }

                using (var session = docStore.OpenSession())
                {
                    // retrieve people using LINQ
                    var people = from person in session.Query<Person>()
                                 select person;

                    Console.WriteLine("Total: {0}", people.Count());

                    foreach (var doc in people)
                    {
                        Console.WriteLine("{0} : {1}, {2}"
                            , doc.Id, doc.LastName, doc.FirstName);    
                    }                    
                }                
            }            
        }

        public class Person
        {
            public string Id { get; set; }
            public string LastName { get; set; }
            public string FirstName { get; set; }
        }
    }

Every document in RavenDB has to have a key, and RavenDB will generate a new key for the document if it has not been assigned already. Here is what happen when I run the code above.

image

I can go to the bin folder and see database that has been created. The folder is just a normal folder although the RavenDB icon is displayed.

image

image

In next RavenDB post, I will run RavenDB server in the console mode and show the RavenDB management studio which can be used to manage RavenDB server as well as see RavenDB in more detail. Enjoy coding!