The move towards micro ORMs

May 16th, 2011 by Gareth / Comments

Many of us know about the apparently recent appearance of micro ORMs thanks to Rob Conery’s Massive followed by Sam Saffron’s (and Stack Overflow’s) Dapper and more. However, having read around the web it is clear that micro ORMs have existed for as long as ADO.NET, but without the publicity. Some developers don’t like their SQL taken away from them and don’t like the idea of using a heavy ORM if they can help it. So they write their own object mapper that works for them. Of course there are many advantages to using a mature fullsome ORM, it just depends on how you look at it and what’s important in your world

I’ve been resisting using LINQ to SQL / EF / NHibernate partly because I was concerned about efficiency and control but mainly because at work I’ve just not needed to change the data access layers nor have I had the opportunity to do so. I inherited a data access layer that mainly uses stored procedures and ADO.NET and there’s no need to change this. There’s nothing wrong with it and it’s stable and switching to an ORM would be virtually impossible. Does a stored procedure heavy application even suit an ORM? Perhaps for reads

But at home it’s different

At home it’s different. I’m building an application that is still in it’s early stages so I can spend time experimenting with micro ORMs. From what I’ve seen so far I like them all because :

  • they are closer to the metal
  • the source code is right there for you to step into
  • they are much faster than full ORMs
  • the learning curve is much shorter

The downside is that you need to know a little SQL to make the most of them, but this excites me! SQL is already a mature ubiquitous DSL for accessing data. If you can talk this language you are at a serious advantage than if you’re relying on an ORM to generate the SQL for you. Dapper and PetaPoco both share a slight optimisation complication in that they both dynamically generate poco mapping methods for your pocos using System.Reflection.Emit.ILGenerator. I tend to skip past that bit in the source for now :) but guess what… these two are the fastest C# based micro ORMs available right now

I’ve experimented a little with Massive, Simple.Data, Dapper and PetaPoco with PetaPoco looking like my personal favourite. I’ve spent most of my experimentation time with PetaPoco so I’ll follow this post up with a list of learning curve problems I had.

Data

Comments

Learning new stuff as a developer

March 12th, 2011 by Gareth / Comments

Constant learning is vital to most careers but it is especially vital for developers. Learning is rewarding and addictive, but also difficult. It takes time, determination and motivation to push yourself out of your comfort zone and reach the next camp in the ascent of your career. There’s no room for stupid pride either so be prepared to :

  • ask stupid questions of people who know what you want to know
  • feel confused after reading that page for the third time
  • bow to those of superior knowledge
  • feel overwhelmed

Ultimately what really matters is that you slowly but surely insert information into your databrain and keep it there.

I started to take learning seriously about 6 years ago. Prior to that I was in the pleasure zone known as IGNORANCE where I thought I knew all I needed to and that I was somehow immune to having to learn stuff. That’s ignorance all over, you don’t know what you need to know so it doesn’t exist, right? Slowly that changed as I started to buy more tech books and write more code in my spare time. My delusions of grandeur were tested to their brittle limits

But I had a problem…. I wasn’t very good at learning. I would read a book but nothing much would happen. I’d forget things I’d read about or used before, or I’d have no frame of reference on which to hang new information. That’s when I begun to take learning how to learn seriously.

Learning how to learn. Is that right?!

Yep that’s right there are loads of techniques for learning stuff. I started with the assumption that I had problems committing information to memory so I got into mnemonics and other memory techniques. I bought half a dozen (that’s six) of the Tony Buzan books and came up with elaborate story methods, journey methods, location methods, peg methods and the beginnings of a number system. Got nowhere with those as I wasn’t able to (or didn’t try hard enough to) translate the kind of programming information I was learning into any of these methods. After about six months (that’s half a dozen) I scrapped it, then moved onto mind maps.

Free your mind with FreeMind

I had a great time with FreeMind. The first thing I did was change the default style and colours to this custom patterns.xml file because out of the box it looks bland (or it did when I started using it). I find mind maps to be a great way of organising information together but in the end I concluded that they are clunky, non-portable and complex. I know the whole point of a mind map is to keep it simple and use minimal and sharp wording but is this suited to learning typical programmer information? Look at this fraction of one of my mind maps and you tell me :

And here’s the same mindmap fully expanded :


Viewing these mind maps is only possible in FreeMind itself (although you can export to a web page and PDF now too). The other problem is that the mind maps are just visually huge and the interface is fiddly. Finally there are just too many little steps to take when you want to note something down. And that’s the whole problem. When learning stuff I want to take notes immediately and move on. For me it has to be transient, simple and unobtrusive.

I still use FreeMind but not for taking learning notes.

In my next post I’ll emit more off-scented verbage about where this all ended up and how I take notes nowadays.

In a nutshell it’s a mixture of low tech and high tech :

  • 6×4″ index cards
  • The excellent ZIM wiki
  • A Samsung Galaxy Tab
  • The Kindle app
  • Photo scanner

Inspiration, Productivity

Comments

ASP.NET MVC [Remote] validation – what about success messages?

January 27th, 2011 by Gareth / Comments

Since ASP.NET MVC 3 it’s easy to validate an individual form field by firing off a HTTP request to a controller action. This action returns either Json(true) if the value is valid or a Json(“error message”) if it is not valid. If you return an error then jquery.validate.js will add your error message to the validation element for the field being validated. It’s easy to setup on your view model :

	[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
[EmailAddress]
[Remote("RemoteValidation_UniqueEmailAddress", "Account")]
public string Email { get; set; }
	

When the user makes a change to the Email field the /Account/RemoteValidation_UniqueEmailAddress action is automatically called on the server. The server side action is just as simple to setup :

	public ActionResult RemoteValidation_UniqueEmailAddress( string Email)
{
   object oResult = false;
   if( Validation.IsEmailAddress( Email) == false)
   {
      return Json( "Please enter a valid email address", JsonRequestBehavior.AllowGet);
   }
   else if( m_oMembershipService.IsThisEmailAlreadyTaken( Email) == true)
   {
      return Json( "This email address is already in use", JsonRequestBehavior.AllowGet);
   }
   else
   {
      return Json( true, JsonRequestBehavior.AllowGet);
   }
}
	

A remote validation error is displayed in exactly the same way as a view would render it. This is because the javascript latches onto the Html.ValidationMessageFor element you setup in your view :


This is ok isn’t it? But…

I want the Email Address label to be bold and red too

In the interests of best practice web form techniques I want the email address label to be bold and red, as well as the error message. To do this I had to hack jquery.validate.js so that it calls a local javascript function with the same name as the server function (with “_response” appended to it) :

	remote: function(value, element, param) {
    if ( this.optional(element) )
        return "dependency-mismatch";
 
    var previous = this.previousValue(element);
    if (!this.settings.messages[element.name] )
        this.settings.messages[element.name] = {};
 
    previous.originalMessage = this.settings.messages[element.name].remote;
    this.settings.messages[element.name].remote = previous.message;
 
    param = typeof param == "string" && {url:param} || param;
 
    if ( previous.old !== value ) {
        previous.old = value;
        var validator = this;
        this.startRequest(element);
        var data = {};
        data[element.name] = value;
 
        $.ajax($.extend(true, {
            url: param,
            mode: "abort",
            port: "validate" + element.name,
            dataType: "json",
            data: data,
            success: function(response) {
 
                //START OF HACK
                var aParts = param.url.split(/\//);//eg; param.url = "/Account/RemoteValidation_UniqueEmailAddress"    ELMS
                oCustomResultFunction = aParts[aParts.length - 1] + "_response";//ELMS
                //END OF HACK
 
                validator.settings.messages[element.name].remote = previous.originalMessage;
                var valid = response === true;
 
                if ( valid ) {
                    var submitted = validator.formSubmitted;
                    validator.prepareElement(element);
                    validator.formSubmitted = submitted;
                    validator.successList.push(element);
 
        //START OF HACK
        var bShowErrors = true;
        if( typeof(window[oCustomResultFunction]) == "function")
        {
            bShowErrors = window[oCustomResultFunction]( true, null, validator);
        }
        //END OF HACK
 
        if( bShowErrors)//HACK
        {
            validator.showErrors();
        }
 
        }
        else
        {
            var errors = {};
            var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
            errors[element.name] = $.isFunction(message) ? message(value) : message;
 
            //START OF HACK
            var bShowErrors = true;
            if( typeof(window[oCustomResultFunction]) == "function")
            {
                bShowErrors = window[oCustomResultFunction]( false, errors, validator);
            }
            //END OF HACK
 
            if( bShowErrors)//HACK
            {
                validator.showErrors(errors);
            }
        }
 
        previous.valid = valid;
        validator.stopRequest(element, valid);
    }
}, param));
        return "pending";
    } else if( this.pending[element.name] ) {
        return "pending";
    }
    return previous.valid;
},
	

And now a client side javacsript function called RemoteValidation_UniqueEmailAddress_response will be called with the result of the remote validation. In this example I know that the function only targets the Email field but it’s wise to check the errors collection that comes back in case other model errors were added in the server function (see the outcommented code below). The aErrors collection is keyed on the client side ID of the invalid field/s :

	function RemoteValidation_UniqueEmailAddress_response( bIsValid, aErrors, oValidator)
{
    if( bIsValid == false)
    {
        /* This bit is optional
        for( var sId in aErrors)
        {
            $("label[for=" + sId + "]").addClass( "error").css( "font-weight", "bold");
        }*/
 
        $("label[for=Email]").addClass( "error").css( "font-weight", "bold");
    }
    else
    {
        $("label[for=Email]").removeClass( "error").css( "font-weight", "normal");
    }
 
    return true;
}
	

The first argument to the function is whether there is an error or not. The second parameter is the errors collection. Now when I enter an invalid email address my form looks like this

That’s better but something is still bothering me

Success messages would be nice

As well as catering for validation errors you now get the chance to provide success feedback as well which can be just as important as error feedback. For example if the user is registering on a site and choosing a username the validation could check that the username is available. If it is then you can present a jolly green tick to the user. This completely removes ambiguiuty, especially if the previous username they entered was already taken and they saw a validation error

One last bit of code :

	var g_bEmailHasBeenInErrorState = false;
function RemoteValidation_UniqueEmailAddress_response( bIsValid, aErrors, oValidator)
{
    if( bIsValid == false)
    {
        $("label[for=Email]").addClass( "error").css( "font-weight", "bold");
        g_bEmailHasBeenInErrorState = true;
    }
    else
    {
        $("label[for=Email]").removeClass( "error").css( "font-weight", "normal");
 
        if( g_bEmailHasBeenInErrorState)
        {
            g_bEmailHasBeenInErrorState = false;
 
            $("#Email").after( "<img style='float:left;' src='<%=Url.Content( "~/Content/img/tick.gif")%>' alt='This is a valid email for this web site' />");
        }
    }
 
    return true;
}
	

Hang on a minute. Why isn’t this functionality in jquery.validate.js anyway? Go to your room!

I didn’t refer once to AJAX because :

  • XML is moribund everywhere but the enterprise.
  • IE had javascript HTTP requests before the web existed.
  • Prior to that you could just screen scrape a hidden iframe for crying out loud!

ASP.NET MVC, jQuery, UI

Comments

My Micro-SAAS Journey

Get the inside story as I work out how to create a micro-SAAS