My Links
Disclaimer

The opinions expressed here are my own and do not necessarily reflect the views of any former, current or future employers or employees of mine.

Saturday
Feb272010

Not as lazy as I thought...

I just ran into an unexpected lazy loading issue using NHibernate, so I thought I'd document it here.

Essentially, the domain has a Parent class (called Parent) which has a collection of Child classes (a property named Children which is an IList). The NHibernate mapping is setup as a lazy-loaded collection, which is very performant when the collection of children is small, which you'd typically find when doing unit testing or integration testing. The bottleneck starts showing up as soon as parent.Children.Add(newChild) is called and the number of children is sufficiently large enough to cause a delay while lazily loading the children.

The simple fix is to setup a bi-directional association between the objects and make sure the cascade goes in both directions.  Once that's done, change 'parent.Children.Add(child);' to 'child.Parent = parent;' and flush the changes to the DB. Now, this change will not help very much if you are going to do queries against the Child collection before persisting the changes to the database (since the child won't be in the collection until a query is done to pull the collection out), but it will keep you from pulling all the Children from the database and into memory in order to simply add a new item to the collection. The next time the parent is loaded and the 'Children' property is referenced it will lazily load all the children, including the new record.

To sum it up: If you have a collection that's lazily loaded, and the 'Child' has a reference to the 'Parent', you're better of setting the 'Parent' of the 'Child' than adding the 'Child' to a collection in the 'Parent' since NHibernate is going to load the other 'Child' objects of the 'Parent' before it performs the Add().

Thursday
Feb252010

Learning the conventions

In effort to sharpen the saw a bit I started playing around with Ruby on Rails last week.  I quickly realized a couple things about Convention over Configuration:

  1. How much busy work is avoided by using Conventions, which is probably why certain projects in the .Net and .Net OSS communities are rushing to add Conventions.
  2. One should probably know what the Conventions are before diving into a project that uses them.

So I did a quick google to get a list of the Conventions and found this post on Ruby on Rails Naming Conventions.

Here's the summary of the post, just in case it ever get's taken down.

Model Naming Convention

Table: orders
Class: Order
File: /app/models/order.rb
Primary Key: id
Foreign Key: customer_id
Link Tables: items_orders

Controller Naming Convention

Class: OrdersController
File: /app/controllers/orders_controller.rb
Layout: /app/layouts/orders.html.erb

View Naming Convention

Helper: /app/helpers/orders_helper.rb
Helper Module: OrdersHelper
Views: /app/views/orders/… (list.html.erb for example)

Tests Naming Convention

Unit: /test/unit/order_test.rb
Functional: /test/functional/orders_controller_test.rb
Fixtures: /test/fixtures/orders.yml



Thursday
Feb252010

Where'd my email go?

I've been a big fan of Google Apps since I setup my first domain (this one), almost 2 years ago. It's dead simple to setup, you get most of the features of a GMail account with the benefit of having your own domain name, they recently added Microsoft Exchange compatibility, and it's free (if you can squeeze all your emails in ~7GB).

We recently migrated one of our domains from Exchange to Google Apps and encountered an unexpected problem.  When forwarding email from an account on one Google App domain (the secondary account) to an account on another (the primary account) the emails would automatically get marked as read and then skip the inbox in the primary account, effectively never showing up on my radar. Not very convenient if you're like me and you live in your inbox.

As a last resort I could have setup my primary account to poll the secondary account for new emails via POP3, but I figured I'd try one last thing before implementing that hack.  I logged my secondary account and turned off the forwarding in the "Forwarding and POP/IMAP" tab, then setup a new filter that would forward email that showed up for "*@secondarydomain.com" to "me@primarydomain.com". Problem solved.

Tuesday
Feb232010

Another reason why Flash won't work on the iPhone/iPad

Listening to Monday's SDR episode, there was a segment about an experienced Flash developer who recently posted a few reason as to why Flash doesn't belong on a touch-based device.  The article mentions the 'hover issue' and the 'right-click issue' but I think it missed another valid issue; scrolling the page vs. being able to drag elements around.  The problem is that the browser's default behavior for 'touch and drag' is scrolling, not dragging.

This problem is not isolated to Flash apps. I tried to use a web app yesterday which uses jQuery to power the user experience. It allows users to drag DOM elements around the page and it simply didn't work; Every time I tried to drag an element the whole browser would scroll in the direction I was dragging.

Friday
Nov132009

The operation has timed out

Actually, it said 'System.Net.WebException: The operation has timed out'... and it said it a bunch of times.  I swear the error log was laughing at me.

Working in C# (.Net 3.5) tonight and had to write a method that contacted a few other sites and downloaded some data.  Simple enough, just loop through the urls, setup the request, get the response and process.

foreach(var url in urls)
{
    var request = WebRequset.Create(url);
    var response = request.GetResponse();
    //... do something with the response
    response.close();
}

Worked like a charm for the first run, so I let it go.  Came back 15 minutes later to a log file full of errors telling me that 'The operation has timed out.'  So, with just a little bit of research I found this post which points out that without a call to request.Abort() you start running into this problem.

So, I added a finally{} block with a request.Abort() in it and everything's been fine.  I have to admit, it feels like a bit of a hack, so I think I'm going to have to do some more research.  Will update here when I know more.

Update:

I found a post on a form that mentioned that setting the HttpWebRequest.KeepAlive might be an issue.  According to the post, when it is true (it's default) it keeps a connection to the remote Url in a connection pool, so that it can quickly hit it again if it has to.  And, if the remote server's keepalive is set to a shorter interval it will close the connection before the WebRequset does, so when the WebRequest tries to use the same request again it throws because it thinks it's getting an open connection to the server.

I tried commenting out the request.Abort() and adding ((HttpWebRequest)request.KeepAlive = false; but ran into the same exact issue about 90 seconds into my tests.  So I'm putting the Abort() hack back in until I get some better info.