6 months into the job

Monday 11th May will see be me 6 months into my new job, my last place I was there for 11 years so it was quite a big thing for me moving on.

The new job is going well, I like the way we go about our work, we talk about it, we plan it, then we try as best we can to do proper test driven development.

Last week saw us starting a new RavenDB based MVC 3 project which will be using Agile techniques using sprints – it will also include some new tools which I havent yet used such as initializer and twitter bootstrapper – more on them to come as I get hands on during the project.

Starting a new project is always great, although we are under pressure to get this out the door, were luck to not having paying customers demanding software releases as soon as possible, this means we don’t cut corners and can produce code which has been thoroughly tested and due to the tools we use we know it’s of decent high quality.

Testing driven development has been quite a mind shift from what I have been used to, in the past I would have written the code and then done some manual testing usually from the front end, so this has been a great leap forward – it’s not the be all and end all of course and code can still contain bugs, however, changing code and knowing if you broke something is very nice.

The main difference has been using Resharper, style cop and unit tests along with a great build system – all checked in code has the same style and formatting which is rather nice.

RavenDB CRUD – How To

Tags

,

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:-
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
    
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    
        Store = new DocumentStore { ConnectionStringName = "RavenDB", DefaultDatabase = "Products" };
        Store.Initialize();
    }
    

    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:-
    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; }
    }
    
  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:-
    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;
            }
        }
    }
    
  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:-
    	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());
            }
        }
    
  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.

Exporting and Importing data with RavenDB

I was wondering how I would go above upgrading from one build version of RavenDB (build 701) to a newer version of RavenDB (build 888) and decided to find out how.

As it turns out like most things in RavenDB its very easy! – the following is how to go about upgrading from one version of RavenDB to another.

Note:- You can do it this way and this is the recomended way here however I wanted to try doing it using importing and exporting the data.

Please not that this was done on my local dev machine at work and not done in a production environment, it wont cover replication as well as some other things to think about but its covers the basics.

I have RavenDB build 701 running from d:\ravedb-build\701 which runs on http://localhost:8080, I then added some test documents to the default database.

I noticed RavenDB had been updated to Build 888 and I began to think how do I get the data out of the old build version and into the new version, having a quick look I soon realised that I need to export data from the 701 build and then import that data into the 888 build.

Here is how I went about it:-

  1. I have RavenDB build 701 running from c:\ravendb\RavenDB-Build-701\ and had 50 documents within it – this runs from http://localhost:8080 as seen below:- Raven Build 701
  2. I then downloaded RavenDB build 888 and ran that from d:\RavenDB-Build-888\ which was empty – this runs from http://localhost:8082 as seen below:- Raven Build 888
  3. Now we can see the differences in the document database as below, Raven 701 build with documents:-
    701 Studio
  4. And the Raven 888 build with no documents as yet:-
    888 Studio
  5. To export and import data within RavenDB you use a tool called smuggler, smuggler can be found within the Smuggler folder and the exe is called Raven.Smuggler.exe
  6. To export the data from RavenDB Build 700 I went into a command prompt window moved into the location of the smuggler exe and ran the following command -> Raven.Smuggler out http://localhost:8080 dump.raven
    Dump of 701
  7. Ok great, now we have exported our data, time to import it into the newer 888 build of RavenDB, to do this we need to a couple of things, firstly locate the dump.raven file in the 701 build/smuggler folder as below:-

    701 dump file location

    And then copy it to somewhere for importing, to make it easy I just copied it to the smuggler folder within the build 888 as below:-

    888 dump file location

    Then go to the smuggler folder for this build and then use the following command -> Raven.Smuggler in http://localhost:8082 dump.raven

  8. We will see Raven ha imported our documents for us:- Data Imported
  9. Lastly lets check in the new build 888 that our documents are there:-
    Documents Imported

And there we go we have moved out documetns from the 701 build to the 888 build, if yo do this you will notice that the index definitions are copied there but havent been built, i.e. youll need to rubuild them manually.

Please feel free to leave a comment if you find this useful or have any questions.

Fusion Log Files are your friend

Firstly this is a very handy tool that a lot of people are unaware of I certainly was, wish I had known about this when trying to fix ClickOnce issues a few years back.

Today I ran into an issue where a small windows forms application was throwing weird exceptions upon start-up, I also had the misfortune of Nuget.exe throwing a tantrum and a colleague asked me had I tried using the Fusion log viewer.

I had a vague idea what it was and remember seeing that mentioned in the event viewer error logs before, but didn’t know much more about it.

The following is how to go about enabling logging for when Visual Studio starts throwing weird errors upon loading up an application.

  1. First of all click Start, and then type in Fusion Log Viewer into the run box, and then right-click on it and run it as an Administrator.

    FusionLog

  2. This will bring up the following:-

    FusionLog
  3. Click settings and here we enable logging and give it a directory path to save the files to.
    Note that the folder needs to be created first, before it will let you give a path:-

    FusionLog
  4. Run the offending app-add in and the log files will be write to the folder you specified.
  5. Upon investigation of these files they usually have a file per missing or wrong assembly, they give you some insight into whats missing as well as the correct version number the code requires.
  • For more info check out Scott Hanselman’s post on this here
  • Let me know if this helps you or any questions then please add a comment.

    Practice Code Kata’s And Learn

    I have been reading up on code katas and think they are a fantastic idea, for those of you who don’t know what a code kata is have then don’t worry read on.

    A code kata is, as I see it, how to take a requirement, break it down into a list of simple tasks and then write the code to solve those problems, pretty much what a developer would normally do anyway but you could tackle the problem using different coding languages/styles/patterns.

    The reason I think code katas are interesting is as follows:-

    1. It will help you learn to use TDD – Use Test Driven Development to write a test before you write the code, write the test, run it so it fails, then write the code to make the test pass and that’s all, do this for each part of the problem your trying to solve.
    2. Estimate how long you think it will take to complete, then time yourself and see how long you take to complete the code kata.
    3. Help improve your typing skills and learn shortcut keys as you try to be more productive and learn to do the kata quicker each time.
    4. Use them at interviews to test your interviewees, see what they come up with and how they think rather than asking them about something they googled the night before the interview.
    5. The best way to learn how to code well is to practice, just like a musician needs to practice, good developers practice too.

    Good examples

    As a good starting point take a look at Roy Osherove’s string calculator – this can be done using a number of different code languages.

    More code Kata’s can be found below:-

    Let me know if you find any more and I will add to the list.

    Accessing RavenDB Studio when using Embedded Mode

    I have seen a few people ask how to go about accessing the RavenDB studio when they use RavenDB in embedded mode, normally you would tend to use embedded mode when unit testing.

    In the following article I show you how to get the RavenDB Management Studio working in an MVC 3 application.

    1. File, New, MVC 3 Application as below:- EmbeddedMode
    2. Choose whatever you prefer in the next window, I chose Internet Application:- EmbeddedMode
    3. Now using Nuget add in the RavenDB Embedded package:- EmbeddedMode
    4. Now we need to add in some details for the application to talk to RavenDB, lets do that now, so edit the global.asax.cs file to have the following code:-

      public static IDocumentStore Store { get; set; }
      
      public static void RegisterGlobalFilters(GlobalFilterCollection filters)
      {
          filters.Add(new HandleErrorAttribute());
      }
      
      public static void RegisterRoutes(RouteCollection routes)
      {
          routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      
          routes.MapRoute(
                      "Default", // Route name
                      "{controller}/{action}/{id}", // URL with parameters
                      new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
                      );
      }
      
      protected void Application_Start()
      {
          AreaRegistration.RegisterAllAreas();
          RegisterGlobalFilters(GlobalFilters.Filters);
          RegisterRoutes(RouteTable.Routes);
      
          Store = new EmbeddableDocumentStore { 
                                                  DataDirectory = "Data",
                                                  UseEmbeddedHttpServer = true
                                              };
          Store.Initialize();
      }
      
    5. Now in order to be able to view the RavenDB Management Studio we need to locate the file Raven.Studio.xap from the packages folder which was created when we added in the Nuget package above.

      The packages folder is located in the directory above the folder in which your solution currently resides, once you locate the packages folder locate the RavenDB-Embedded(version number) folder in my case this is RavenDB-Embedded.1.0.701 – the file we are looking for is in the packages\RavenDB-Embedded.1.0.701\lib\net40\

      Copy the Raven.Studio.xap to the root of your website and now try running your MVC website.

    6. Once that loads up now browse to http://localhost:8080 and the RavenDB Studio should load up – and that’s you.
    7. If you see this:- EmbeddedMode

      It means you havent copied the Raven.Studio.xap to the root of your website.

    I hope this helps someone out.

    Profiling your RavenDB MVC application

    Your application is starting to take shape and you want to be able to quickly see what’s going on when using RavenDB.

    Step forward the in-built profiling dll which is very easy to set up and get going with, lets implement that along with MiniProfiler.

    1. Add the Nuget package MiniProfiler.RavenDb to your application
    2. Add the Raven.Client.MvcIntegration dll which can be found in the Client folder when you download the source for RavenDB
    3. Add the following to your global.asa.cs file:-
      protected void Application_BeginRequest()
      {
          if (Request.IsLocal)
          {
              MiniProfiler.Start();
          }
      }
      

      and then :-

      protected void Application_EndRequest()
      {
          MiniProfiler.Stop();
      }
      
    4. Add the following to your global.asa.cs file in the Application_Start event:-

      Raven.Client.MvcIntegration.RavenProfiler.InitializeFor(Store);
      MvcMiniProfiler.RavenDb.Profiler.AttachTo((DocumentStore)Store);
      

    5. Lastly add the following lines into your _Layout.cshtml file in the Shared folder, under Views:-

      @MvcMiniProfiler.MiniProfiler.RenderIncludes()
      @Raven.Client.MvcIntegration.RavenProfiler.CurrentRequestSessions()
      

    That’s it – you have now adedd the built in profiler and MiniProfiler for RavenDB, run your application and you can
    see that in the top left hand corner you can view the details of whats going on in both profilers:-

    MiniProfiler for RavenDB looks like this:-

    MiniProfiler

    and this:-

    MiniProfiler 2

    while with the RavenDB profiler we see something like this:-

    RavenDB Profiler

    The in-built profiler from RavenDB shows us how long the query took, the status, result, Method, Url, Query and Actions as well as the actual request details.

    All in all both profilers are very hand and very easy to install – go get them installed.

    RavenDB Hints and Tips

    RavenDB Here is a list of hints and tips if you’re looking for some help with RavenDB.


    • Sign up for the mailing list where you can see other people’s previous questions and answers to problems on the View the Google Group.
    • To make sure RavenDB doesn’t clash with routing used in MVC change the global.asa.cs file from:-

      {controller}/{action}/{id} to {controller}/{action}/{*id} – Note the * next to the {id} or you can do this.

    • If I choose the Embedded version of RavenDB how do I start the server – to start the RavenDB server locate the RavenDB folder and then look for the server folder and then run Raven.Server.Exe
    • If I install RavenDB using Nuget then what do I do, locate the packages folder which is in the folder one above the solution you’ve added it to on the file system, locate the RavenDB folder and then look for the server folder and then run Raven.Server.Exe
    • How do you view the RavenDB Studio – easiest way is to browse to http://localhost:8080, that’s the default location of installation when you first run the Raven.Server.Exe
    • Unit testing – how best to go about it – the recommended way to go about this is by using the EmbeddedDocumentStore
      which is basically all done in memory, you can set it up like this:-

      var documentStore = new EmbeddableDocumentStore
      {
          DataDirectory = "Data",
          RunInMemory = true,
          UseEmbeddedHttpServer = true
      };
      
    • Good RavenDB Samples RavenOverFlow and Racoon Blog

    If your stuck with something give me a shout I’ll see if I can shed some light, I’ll be adding more tips as I learn more RavenDB.

    Skillsmatter RavenDB Course Review

    RavenDBOn Feb 28th and 29th of February I attended the Skillsmatter RavenDB course in London with Itamar Syn-Hershko, course details here.

    Itamar is a developer on RavenDB and works with Oren aka Ayende from Hibernating Rhinos in Israel and this was a chance to learn from one of the guys who works on RavenDB.

    The course was a 2 day course covering a wide range of features of RavenDB including:-

    • Principles of RavenDB
    • Getting started with RavenDB
    • CRUD operations
    • The basics of querying
    • Advanced querying
    • Document based modeling
    • Using Includes for better performance
    • Caching and cache utilization
    • Creating static indexes
    • Map/Reduce
    • Extending RavenDB
    • Replication, Sharding & Scale
    • Full text search

    The course covers a lot of content and you’re given exercises to do which was very useful in finding out how to properly use parts of RavenDB as well as learn how to go about a certain task the recommended way.

    I have come away from the course with a much better understanding of the how and why and that’s the main reason why I wanted to go on the course in the first place and I cant wait to get started using RavenDB on our upcoming project.

    From asking a number of questions about RavenDB its clear to me that RavenDB has a lot to it, there is a lot to learn about it but it has a number of great features which are very powerful and yet very simple to use, some of the things that stood out for me where the following:-

    • Safe by default – this means that it stops the user from writing code that is requesting too much data, and limits the number of requests that each session is allowed to make.
    • Lucene – searching using Lucene provides a fantastic way to search and in Raven we can utilise the power of Lucene to even have full text search capabilities.

    The course itself cost £1250 and was well worth it – anyone thinking about going on the upcoming courses I would recommend it to them for definite, details on the next RavenDB course they are hosting can be found here.

    Skillsmatter RavenDB Course

    On the 28th and 29th Feb I attended the RavenDB Course at Skillsmatter in London, details on the next RavenDB course they are hosting can be found here.

    Skillsmatter is located in central London and very easily accessible, being a short taxi ride from Liverpool Street train station – upon arrival we were warmly welcome and asked to register and make our food choices for the first day of the course.

    Skillsmatter is quite a fair size and has several training rooms upstairs and an area downstairs for talks and presentations, many which are given by user groups and can hold id say about 70 people (with room for more).

    Our course took part in one of the smaller rooms which was perfect for our course, plenty of power/access points, projecter and whiteboard(s), all well laid out and just what you’d expect really.

    The food at lunch was great and the staff there were very friendly and very helpful, really nice people.

    On day 2 of the course we went to the pub for lunch and again everyone was very friendly and keen to ask us about how we were enjoying the course and keen to know if we were enjoying out training course.

    For anyone looking for a great training venue or a place to hold a user group meeting in London then this would be an ideal place to go – the courses they run are great and the list of courses is very good indeed

    Follow

    Get every new post delivered to your Inbox.