Login | Register  
View Article

Current Articles | Categories | Search | Syndication

RavenDB & WheelMUD - Take 1

I spend a few hours learning how to use RavenDB yesterday. I first read through the tutorials and documentation on the home page for RavenDB. Unfortunately, the docs are way out of date, as the codebase for RavenDB appears to be moving and changing rapidly.

The first hurdle was that the documentation doesn't explain what namespaces are needed to use for what functionality. This seems to be a frequent problem an 3rd party APIs. I'm specifically testing the embedded stuff. I used the latest build, which is RavenDB-Build-206.

Here's how you setup saving:

       using Raven.Client.Client;

        public void Save()
        {
            var store = new EmbeddableDocumentStore { DataDirectory = DALUtils.GetDbPath() };
            store.Initialize();

            var session = store.OpenSession();
            session.Store(this);
            session.SaveChanges();
            session.Dispose();
        }

My take-away from this code is that saving to the datastore is EXTREMELY easy. So the steps for saving are:

  1. Create an EmbeddableDocumentStore.
  2. Give it the path you want it to create the document files in.
  3. Initialize the data store.
  4. Create a session.
  5. Use the session to actually store. Note that this does not actually save the current document.
  6. Save the changes.
  7. This is optional, but always a good idea, dispose of the session.

Now the hard part, at least to me, is retrieving this back. I have been able to look at the actual document that got stored. I used that knowledge to write a simple function that loads thae class document from disk. The raw JSON for this document looks like this:

{
    "Name":"CrashTestDummy",
    "Password":"dummy",
    "Gender":"Male",
    "TimeInstantiated":"12/5/2010 10:27:44 PM"
}

The properties were declared like this:

    public enum GenderTypes
    {
        Male,
        Female,
        Neuter
    }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name for this player.</value>
        public string Name { getset; }

        /// <summary>
        /// Gets or sets the password.
        /// </summary>
        /// <value>The password.</value>
        public string Password { getset; }

        /// <summary>
        /// Gets or sets the gender.
        /// </summary>
        /// <value>The gender.</value>
        public GenderTypes Gender { getset; }

        /// <summary>
        /// Gets or sets the time instantiated.
        /// </summary>
        /// <value>The time instantiated.</value>
        public string TimeInstantiated { getset; }

The metadata is this:

{
    "Content-Encoding":"gzip",
    "Raven-Entity-Name":"PlayerBehaviors",
    "Raven-Clr-Type":"Behaviors.PlayerBehavior, Behaviors"
}

 Loading this dynamically like I do from databases has eluded me. You normally would use a LINQ query to get the object. These three queries work:

from doc in docs
where doc.Name == "CrashTestDummy"
select new { doc.Name }

from doc in docs
where doc.Name == "CrashTestDummy"
select doc

from doc in docs
where doc["@metadata"]["Raven-Entity-Name"] == "PlayerBehaviors"
select doc

What is baffling me specifically, is how to create an index that I can query against. I got the queries above, after I read an entry in the ravendb Google Groups.

The previous version of the save code, just saved the properties stored in a dictionary. So the old document looks like this:

{
    "Id":"57b7b3a0-ad7b-46e1-bb92-d0bb879d6522",
    "Name":"CrashTestDummy",
    "Password":"dummy",
    "Gender":"Male"
}

The metadata is this:

{
    "Content-Encoding":"gzip",
    "Raven-Entity-Name":"DictionariesOfStringsOfStrings",
    "Raven-Clr-Type":"System.Collections.Generic.Dictionary`2[]System.String, mscorlib[]System.String, mscorlib[], mscorlib"
}

So to load this I did this:

        public Dictionary<stringstring> Load(string playerName)
        {
            var session = _store.OpenSession();

            var playerProperties = session.Load<Dictionary<stringstring>>("dictionariesofstringsofstrings/1");

            session.Dispose();

            return playerProperties;
        }

I haven't changed this to work with the new save method, which uses the actual PlayerBehavior class for saving.

So this is as far as I've gotten by myself. I'm going to need to post some questions on the ravendb Google Groups, to move me forward from my current rut.

The management UI is not out yet, but I did find a workaround. RavenDB comes with a built-in server. I copied the data folder into the Data folder that sits on the same directory as Raven.Server.exe. This is a minuature web server. Once you start this server, you point your browser to http://localhost:8080 to see the web UI. That was good enough to let me examine the documents.

Anyways, I'm pretty tired, so I'm going to stop here.

posted @ Monday, December 06, 2010 11:32 PM by Fastalanasa

Previous Page | Next Page

COMMENTS

Interesting. I don't have time to add much but I wouldn't consider Disposing optional; if it implements the pattern, we have to assume there's a reason to call it, and that reason might not be immediately apparent, or might become more important as their code changes in the future. I'd wrap that session object with "using" (and even simplifies the method) like:

using (var session = _store.OpenSession())
{
return session.Load...
}

posted @ Tuesday, December 07, 2010 3:25 AM by Karak


The using block is the recommended way of doing it. :) Ayende also recommends that the document store be made a singleton. That's why I said that the Dispose is optional.

posted @ Tuesday, December 07, 2010 8:48 AM by Fastalanasa


posted @ Tuesday, January 04, 2011 10:35 AM by SystemWidgets - Taming IS Operations


Only registered users may post comments.
Copyright 2007-2012 by WheelMUD  | Terms Of Use | Privacy Statement
Google Analytics Alternative