Lazy Loading/Eager Loading

The NHibernate FAQ has a new post about complex object graphs and lazy loading.  If you use NHibernate (or, ActiveRecord -- which makes NHibernate a whole lot easier), it's worth a look.  The technique described can greatly improve the way your app interacts with the database.  OR mappers are nice, but you need to make sure you understand what is happening with the database calls that are made automatically by your OR framework.

If you're using ActiveRecord, here's a few more items regarding lazy loading:

Enabling Lazy Loading in ActiveRecord

Tuning ActiveRecord

Combating the Select N + 1 Problem In NHibernate

Posted by PSteele | with no comments

Navigating around in the VS.NET IDE

Last week, Bill Wagner and I were providing some C# training for one of our clients.  Bill showed the class how to use F12 to jump to the definition of a method.  One of the students asked how to go back to your previous position and Bill didn't know the key binding off hand.

As someone who comes from a VB6 background, I've maintained my VB6 keyboard mappings since I moved to C# in 2003.  Navigating around inside the VS.NET IDE has been a no-brainer for me since all of the keystrokes I used for the 7 or 8 years of VB development are the same in VS.NET -- assuming you use the VB6 keyboard layout.

I decided to see if C# has a default key binding to jump back to your previous positions after jumping to a method definition using F12.  First off, I wanted to see what IDE command is mapped to my "go back" function.  I pulled up the VS.NET IDE keyboard options, clicked on the "Press shortcut keys" texbox and hit the keyboard keystroke I use for jumping back to my previous position (Ctrl+Shift+F2):

 image

Looking in the "Shortcut currently used by" field, I see "View.NavigateBackward" is the command used in the IDE to navigate back to your previous position.  Now I changed my keyboard mapping scheme to C# and entered "View.NavigateBackward" into the "Show commands containing" field:

image

So I see control and "-" (minus) is the keystroke to jump back in C#.  I changed my IDE settings to use C# and tested this out.  Sure enough, I can use F12 to jump to a method definition and then ctrl+- to return to my previous position -- sort of like having my own little callstack within the IDE.  :)

And now I've changed my settings back to VB6 mapping scheme since I'm a creature of habit!

Posted by PSteele | 1 comment(s)

LINQ: Deferred Execution

Another interesting tidbit I learned about at the summit was deferred execution of LINQ queries.

Here's an example that highlights what deferred execution means to you.   Let's create a Customer class and then build up a list of customers:

   1: public class Customer
   2: {
   3:     public int ID { get; set; }
   4:     public string Name { get; set; }
   5:     public double Balance { get; set; }
   6: }
   1: static List<Customer> GetCustomers()
   2: {
   3:     return new List<Customer>()
   4:     {
   5:         new Customer {ID = 1, Name="Bill", Balance = 22.50},
   6:         new Customer {ID = 2, Name="Bob", Balance = 0.00},
   7:         new Customer {ID = 3, Name="Joe", Balance = -5.00}
   8:     };
   9: }

Now assume we're going to run a query to find all Customers whose first name begins with a particular letter (supplied in a variable):

   1: var customers = GetCustomers();
   2:  
   3: string firstLetter = "B";
   4: var query = from c in customers
   5:             where c.Name.StartsWith(firstLetter)
   6:             select c;
   7:  
   8: firstLetter = "J";
   9: foreach (Customer c in query)
  10: {
  11:     Console.WriteLine(c.Name);
  12: }

What do you think prints out?  Due to deferred execution, the application will only print "Joe", not "Bill" and "Bob" as you might expect.

The code executed in line 4 only builds the query into a query expression tree.  And that expression tree includes a reference to the "firstLetter" variable, not its contents.  The expression tree is not executed until line 9 when a foreach loop is used.  As a result, the value of the "firstLetter" variable is not obtained until line 9.

So be careful how you use locally-scoped variables in your LINQ queries and be aware of deferred execution in LINQ queries.

Posted by PSteele | 1 comment(s)

Extension Methods: Behind the scenes

One of the sessions I was able to attend (and talk about) at the MVP Summit involved some of the new features of C# 3.0.  My day job still has me doing a lot of C# 2.0 stuff so I haven't dived in too deeply to the new 3.0 stuff.  This was my opportunity to get the information directly from the C# language PM Mads Torgersen.  One thing I found interesting was how extension methods were implemented.

If you're not familiar with extension methods, here they are in a nutshell (and simplified): Extension methods allow you to add new methods to existing classes -- classes that you don't have source code access to and can't recompile with the new method.  In reality, you're not truly adding new methods, but the IDE experience makes it look that way so it flows very nicely.

First, let's look at how we'd tackle a problem without extension methods.  We have a simple Customer class.  I've used C# 3.0's auto-properties to allow me to quickly define the class:

   1: public class Customer
   2: {
   3:     public int ID { get; set; }
   4:     public string Name { get; set; }
   5:     public double Balance { get; set; }
   6: }

Now let's create a list of customers since we're going to iterate over them later:

   1: static List<Customer> GetCustomers()
   2: {
   3:     return new List<Customer>()
   4:     {
   5:         new Customer {ID = 1, Name="Bill", Balance = 22.50},
   6:         new Customer {ID = 2, Name="Bob", Balance = 0.00},
   7:         new Customer {ID = 3, Name="Joe", Balance = -5.00}
   8:     };
   9: }

Note that in the GetCustomers code above I'm utilizing C# 3.0 property initializers too to make this demo simple and concise.

Now we get to the meat of the problem.  First off, we're assuming that the Customer class is in another DLL that we don't have source code for it.  We'd like to know which customer's are delinquent, i.e. a balance less than zero.  It would be easy to simply loop through and check the Balance property, but we'd need that check everywhere we look for a delinquent customer (reports, inquiries, lookups, etc...).  And what if our client decided to change the definition of "delinquent" (for example "a balance less than -10.00)?  We'd have to change that balance check everywhere.  Instead, we'll create a utility method for this (since we can't simply add it to the Customer class):

   1: public static class MyExtensions
   2: {
   3:     public static bool IsDelinquent1(Customer c)
   4:     {
   5:         return c.Balance < 0;
   6:     }
   7: }

(You'll see why I called it "IsDelinquent1" and not simply "IsDelinquent" shortly).  We created a static class and created a utility method that will tell us if a customer is "delinquent" (based on our client's current definition).  Now let's do a quick check to find delinquent customers:

   1: private static void Method1()
   2: {
   3:     var customers = GetCustomers();
   4:  
   5:     foreach (Customer c in customers)
   6:     {
   7:         if (MyExtensions.IsDelinquent1(c))
   8:         {
   9:             Console.WriteLine(c.Name);
  10:         }
  11:     }
  12: }

Pretty simple.  However, it is a little verbose.  Let's now look at how we can utilize extension methods to make this cleaner.

We go back to our static "MyExtensions" class and add our extension method.  It's important to note that extension methods can only be defined in static classes that are contained directly in a namespace (i.e. not a nested class).

   1: public static bool IsDelinquent2(this Customer c)
   2: {
   3:     return c.Balance < 0;
   4: }

This looks almost exactly like the first method (the code block is identical).  We've simply added the "this" keyword at the beginning of the parameter list (before the "Customer" reference).  This tells the C# compiler (and the VS.NET IDE) that "IsDelinquent2" is an extension method on "Customer" since it appears right before a Customer parameter.  That's the only difference!

Utilizing this extension method makes the loop code much cleaner and easier to read:

   1: private static void Method2()
   2: {
   3:     var customers = GetCustomers();
   4:  
   5:     foreach (Customer c in customers)
   6:     {
   7:         if (c.IsDelinquent2())
   8:         {
   9:             Console.WriteLine(c.Name);
  10:         }
  11:     }
  12: }

Very nice!

Now the reason I've got static code all over this demo is because you can take all of the code, slap it into a VS2008 Console application and compile it (make sure the MyExtensions class is not nested within the default "Program" class).  Now fire up ILDASM and look at the decompiled IL for both "Method1" and "Method2" (I named them differently so you could compile them together and examine the differences).  You'll see that the IL code is exactly the same, byte for byte.  That's because extension methods are not a CLR addition, they are a C# addition.  They're a neat "macro" that the C# compiler automatically does for you.

It's a pretty neat implementation and can make interaction with external libraries a bit easier.  And if you're wondering, yes, the extension methods are listed as a method directly on the class with Intellisense.  They get a slightly different icon (I wasn't able to capture it with my screen capture utility) and the tooltip for the method in Intellisense has "(extension)" at the beginning of the method name.

Posted by PSteele | 2 comment(s)

Adding Action Filters to MonoRail Controllers

Neal Blomfield made interesting use of MonoRail filters.  Check it out.

Filters are commonly used for tasks like authentication and localisation, however by default they run for all actions in the controller and you must specify which actions to exclude using the [SkipFilter] attribute. In a majority of cases this works well as the filter is designed to handle cross-cutting concerns (which by definition affect most if not all actions), however there are times when you want to apply the filter to a minority of the actions in a controller, or add action specific metadata that may vary the way the filter executes depending on the action. Recently I came across just such a scenario…

Posted by PSteele | with no comments

Sessionless MonoRail Controllers

I saw this post on the Castle Users mailing list and thought it was interesting and I wanted to post it.

By default, MonoRail controllers assume that ASP.NET session state is enabled.  If you disable ASP.NET's session state inside web.config, you'll get an exception when MonoRail tries to process the request.  What you need to do in this situation is to add a ControllerDetails attribute to your controller and set "Sessionless = true".  Thanks to Roelof Blom for posting a quick solution.

Posted by PSteele | with no comments

MVP Summit 2008

I'm now at the MVP Summit in Seattle.  This is my first summit in 5 years and I'm pretty excited!  They've got a great line-up of sessions, speakers and events.  It'll be a busy four days.  I'll try and blog as much as I can (anything that isn't NDA).  As a fan of the Castle Project (especially MonoRail), I'm looking forward to some of the ASP.NET MVC sessios.

Posted by PSteele | 1 comment(s)

NHibernate 2.0 Statistics and a MonoRail filter

This looked pretty cool.

Just to try this out I created a MonoRail filter that checks for "nhibstats" in the query parameters of the request. If the parameter is found it will turn on the nhibernate statistics, this is done before the controller action is executed. After the action as completed it will add the stats data to the PropertyBag so the view can access it.

Posted by PSteele | with no comments

Home Appliance Repair

Last night, instead of finalizing an app I'm working on for a client, I was playing around with my dishwasher.  I'm going to be at the MVP Summit next week and did NOT want to leave my wife alone with the kids and no working dishwasher!  It reminded me of my experience a couple of years ago when I had a furnace that didn't want to work.

A furnace (a gas one as we have) seems like such a simple thing: The termostat tells the furnace the house is too cold and the furnace turns on to blow hot air through the house.  Once the house is warm enough, the thermostat tells the furnace to turn off.  I'm sure many of our clients think the software we bulid is a pretty simple process: Enter a few numbers, drag a few sliders, hit "Submit" and you get your data plotted in a nic pie chart.  Easy!  But just as we developers put in so much work "behind the scenese" (input validation, unit tests, parameter validation, etc...) so too, do gas furnaces.

Our furnace (like many other gas furnaces, I suspect) has quite a complex cycle between the thermostat saying "I need heat" and actually getting heat.  First off, the blower spins up.  Time for hot air?  Not yet.  First, the gas has to flow and something has to ignite it.  Our system is pilot-less so there's a heater element.  This device is basically a 2-inch piece of material that glows red-hot when the system tells it to.  That is actually the second step in the process.

Now the gas flows right?  Nope.  Before the gas flows, the system must ensure that the heater element is hot enough to ignite the gas.  If the heater element was broken and the gas started flowing, instead of heating the house you'd be pumping gas throughout the house.  Not good!  So there's a heat sensor placed near the heating element.  The system tells the heating element to "glow hot".  It then waits for the heat sensor to detect that the heating element has gotten hot enough to light the gas.  Once this happens, then the system opens the gas flow, the gas ignites and we have hot air to warm up the house.

Not as simple as I had originally thought, but as I learned this, I definitely saw the parallels in my day job of software development.  Granted, a fault in my system may generate a nasty error message.  A fault in the heater could have much more dire consequences!

Oh yeah, the dishwasher?  I don't know what went wrong with that.  After pulling it out (its an under-the-counter model) and looking around, nothing seemed out of place.  So I turned it on and it started working fine (you know -- the client says, if I do "this" it breaks.  You do "this" and it works).  Before putting it back under the counter I want to run a few more tests before I mark this bug as "could not duplicate"...

Posted by PSteele | 4 comment(s)

Hats off to CATS!

No, not the musical!

My Lenovo (IBM) X60T Tablet started having a problem about a month ago.  The bottom two-inches of the LCD display was flickering/smearing/not displaying properly.  I noticed that if I gently squeezed one corner of the display, the problem went away but returned within a few days.  Further squeezing lasted only a day or two, then hours, then it was flaky all the time.

My warranty expires soon and this seemed like a warranty issue.  I did some research and found a local company, CATS CO, that is an authorized Lenovo repair center.  I went through the fun of backing up EVERYTHING off the machine.  Double-checked my backups, removed the hard drive and took it in for service on Tuesday 3/25 (in the afternoon).  They said they'd call in 3 to 4 days with an estimate.

On Monday morning (3/31) I recieved a phone call at 10:00am.  My tablet was fixed and ready to be picked up.  It was a warranty issue and I owed nothing.  Sweet!  I was expecting to be without my laptop for at least a week, perhaps a little longer if they needed to order parts.  Needless to say, I was very happy with the service I got from CATS CO and would recommend them to anyone in the southeast Michigan area needing to get a laptop repaired.

Posted by PSteele | with no comments
More Posts Next page »