Thoughts on MicroOrms

August 2nd, 2011

I’ve been spending some time getting my head wrapped around the idea of MicroOrms lately.  A lot of this has to do with some of the scalability/caching issues I’ve been having with NHibernate.  Don’t get me wrong, I still love NHibernate, but it can be a bit of a beast when you are really trying to drive performance, there is a lot of overhead in there.  Besides, my general rule has been a good ORM can handle 80-90% of your queries, and then performance tune out as needed.  I’m at the performance tuning part now.

BTW: if you are using Entity Framework you are in the same boat.

So the question is, what to do with that last 10-20% that you need performance on?  Previously I had gone straight to Ado.Net, or used my own FluentAdo project.  But a few new projects have dropped in on the scene and it was time to take a look.

Let’s start off with some requirements:

  1. Don’t be a pain to setup.
  2. Don’t hork up my domain model (I have NHibernate for that).  POCO preferred.
  3. Be able handle multiple result sets (something NHibernate does not do well)
  4. Preference executing raw sql, not an api. 
    I don’t need:
  1. A custom query api for constructing sql.
  2. Change tracking
  3. Caching
  4. Lazy Loading
  5. Automatically loading child objects
    Basically, be simple, be light, be fast, don’t be another NHibernate. 

Now the Contenders:

    • Dapper
    • Simple.Data
    • Massive
        • Dapper

        Dapper is my current favorite.  I deals with POCO objects, setup is very simple, very little overhead and ceremony.  That said, it is probably the rawest for dealing with sprocs.  But for a bare metal way of loading domain objects, this guy is hard to beat.

        Here is a sample query:

      var customer = _connection.Query<Customer>(
          "select * from dbo.Customers where CustomerId = @id",
          new {id = 1})
          .FirstOrDefault();

      Basically, Dapper handles all of my requirements with ease.  I almost forgot to mention, Dapper is compatible with .Net 4.0 and 3.5.   That is a huge win for me.  Plus, the guys on Stack Overflow are using it, which makes for an easy “sell” to my management team.

       

      Simple.Data

        Simple.Data is also very interesting.  It makes extensive use of .net 4.0 and the dynamic.  Simple.Data is fairly ORM’ish, in that it seems to scan your database schema and dynamically add methods for retrieving data.  But it still uses POCO classes so I am good with that.

      Here is a sample query:

    var db = Database.Open();
    var customer = db.Customers.FindByCustomerId(1);

    To get that to work I defined the customer class with a CustomerID…and that is it.  Dapper came up with the FindByCustomerId part.  It also adds stored procs as well, so if I have a sproc called “GetCustomers”, I can call:

    db.GetCustomers()

    It is just scary what is going on here.  Granted there is a down-side to this system – albiet minor.  There is a bit of overhead while Simple.Data scans your database schema and gets setup.

    Verdict: I don’t mind Simple.Data, but the .Net 4.0 only part is a problem, plus it strays a bit into becoming a ORM – a bit too much API, but nothing obnoxious.

    Massive

    I should have known how this one would turn out ahead of time, but I really didn’t want to believe it.  When I was young and foolish I was a SubSonic guy.  Truth is, I read Rob Connery’s blog religiously.  But I moved passed SubSonic and onto NHibernate and never looked back.  Heck, I moved passed Active Record and onto Repository Pattern.  (Since then I’ve moved on again to Query/Command Pattern, but another time for that).

    First off, Massive horks up my domain model.  Each entity has to inherit from DynamicModel.  So before my model looked like this:

    class Customer
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
    }

    Now, Massive-fied:

    class Customer: DynamicModel
    {
        public Customer(): base("Default")
        {
            TableName = "Customers";
            PrimaryKeyField = "CustomerId";
        }

        public int CustomerId { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
    }

    And that “Default” in there, that is the name of my connection string.  Wonderful.  Also, because my table names are plural, I have to specify the name of my table for them in EVERY SINGLE CLASS.

    Now, how to query:

    var tbl = new Customer();
    var customer = tbl.Single(1);

    Smack-dab, back to Active Record.

    Also, I didn’t see anything on how to parse multiple result sets.

    Go to Rob’s site and you will see more samples.  Needless to say, it is off my list.  Granted, Massive is still much less overhead than NHibernate and Entity framework, but there is too much API there for me, too much setup, I don’t get my POCOs, etc.

    • http://biacreations.com Jim Geurts

      I believe “Dapper came up with the FindByCustomerId part.” is meant to read “Simple.Data came up with the FindByCustomerId part.”

    • http://www.stevesdevbox.com Steve

      I’ve been playing around with PetaPoco, which syntactically is very similar to Dapper and very much like it.

    • Nick

      Great post Chris. I’m interested in hearing more about Query/Command Pattern. 

    • CodingSamurai

      From Massive documentation …

      “//you don’t have to specify the connection – Massive will use the first one it finds in your config”

      Reading for comprehension is just as important as reading for speed …

      That said, PetaPoco is great … and got all of its ideas from Conery’s SubSonic/Massive …

    • http://www.outsource-website-development.com/outsource-drupal-web-developers-india.html outsourcing india drupal

      Of course we got more ideas about this microorms.. Really very interesting to read this one. We are expecting like this information from you.. thanks a lot..
      outsourcing web developers | outsourcing joomla web development