It hardly seems that I've finished writing about Microsoft's PDC (Professional Developer's Conference), and we're back in action with Tech-Ed 2004, in lovely San Diego. The conference was typical Microsoft fun, with too many afternoon ice cream bars and not nearly enough sleep. (Speaker Richard Campbell came up with the perfect solution to the “too many popsicles and not nearly enough Haagen-Dazs” problem?he made a quick shopping trip and raffled off the good stuff in his session on Friday. People were clamoring to ask questions and win a pre-lunch ice cream bar.) Being as Chez Getz is only a few hours from the venue my old pal, the Aussie Adam Cogan (formerly referred to as “the ironman” in this column) stayed for a week after the conference to speak at a few local user groups.

As has become the pattern when Adam visits, we exercised a lot. Maybe too much. Luck would have it that I happen to live on a hill on the side of which happens to be Los Angeles' steepest street. Eldred Street climbs 219 feet in a 33% grade on the side of our hill. One afternoon we bicycled past this vicious climb, and I mistakenly pointed out the sheer hillside to Adam. Immediately he was climbing up, taunting me to follow. Like a fool, I accepted his challenge. I fell off about 1/3 of the way up the hill. Adam pushed on until he could no longer turn the crank without the wheels slipping on the dusty street. He quickly walked his bike up the incredibly steep street. I, on the other hand, could only trudge four or five paces at a time, stopping occasionally to suck in a little breath. It took me upwards of 30 minutes to stagger up the hill, pushing the bike and fighting the urge to lose what little there was in my stomach. Of course, once you climb the street, there's a series of 100 or more stairs required to finish the climb to the top. Funny, as we were gasping near the top (OK, just me) we saw a bottled water delivery truck attempt the climb. It finally gave up and backed its way up the hill, so as to take advantage of the lower reverse gear (and to avoid tipping over, I imagine). Only Adam could convince me to even attempt such a stupid feat. (In case you want to corroborate the facts, check out the article from the Los Angeles Times at http://www.latimes.com/news/local/la-me-surround21aug21,1,7369970.story.)

Speaking of Adam, during his TechEd session (discussing SQL Reporting Services and Exchange data), he pointed out an innocent block of code, showing how he has his employees fill a DataSet. This simple example prompted another attending speaker to blurt out, in the middle of the session, in front of 300 people, “Why would you ever do it that way?” (Please don't do this. It's pretty darned rude to interrupt a large conference session. I was astounded. Better to discuss such things in private after the session.) Adam and I have been arguing about this example for the past three weeks, and I'm afraid the discussion isn't over. As if it really mattered…

Here's a sample code fragment, using the SqlClient namespace:

SqlConnection connection = new SqlConnection("Data Source=(local);" +
    "Integrated Security=SSPI;" +
    "Initial Catalog=Northwind");
    
SqlCommand command = new SqlCommand("SELECT * FROM Customers", connection);
SqlDataAdapter adapter = newSqlDataAdapter(command);
DataSet ds = new DataSet();
try
{
    connection.Open();
    adapter.Fill(ds);
}
finally
{
    connection.Close();
}
// Now use the DataSet.

My theory, and that of the blurty fellow speaker, is that there's nothing really wrong with this code, but there's no need to explicitly open and close the connection in this scenario. The SqlDataAdapter (or any other data adapter) object preserves the state of the connection it's given. If you call the Fill method with an open connection, it leaves the connection open. If you call it with a closed connection, it opens the connection retrieves the data and fills the DataSet, then closes the connection and returns it to the connection pool (if that feature is available). Given my point of view, Adam's code block has the exact same behavior as the following:

SqlConnection connection = new SqlConnection("Data Source=(local);" +
    "Integrated Security=SSPI;" +
    "Initial Catalog=Northwind");
    
SqlCommand command = new SqlCommand("SELECT * FROM Customers", connection);
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataSet ds = new DataSet();
adapter.Fill(ds);
// Now use the DataSet.

If I was going to write code that opened the connection, I would personally take advantage of C#'s using block, which handles the necessary cleanup for you. Of course, that doesn't make Adam happy, because it does its cleanup implicitly, and developers can't actually see the code that closes the connection.

Adam's theory is that inexperienced developers working for him have a hard time with the fact that sometimes you must explicitly open and close a connection, and other times you don't. For example, when working with a DataReader, you really do have to open your own connection:

SqlConnection connection = new SqlConnection("Data Source=(local);" +
    "Integrated Security=SSPI;" +
    "Initial Catalog=Northwind");
    
SqlCommand command = new SqlCommand("SELECT * FROM Customers", connection);
SqlDataReader reader;
try
{
    connection.Open();
    reader = command.ExecuteReader();
    // Now use the reader.
}
finally
{
    connection.Close();
    if (reader != null)
    reader.Close();
}

Of course, even in this case, you needn't worry about closing the connection?you can simply tell the ExecuteReader method that you want ADO.NET to handle this for you, when the reader gets closed:

SqlConnection connection = new SqlConnection("Data Source=(local);" +
    "Integrated Security=SSPI;" +
    "Initial Catalog=Northwind");
    
SqlCommand command = new SqlCommand("SELECT * FROM Customers", connection);
SqlDataReader reader;
try
{
    connection.Open();
    reader = command.ExecuteReader(
    CommandBehavior.CloseConnection);
    // Now use the reader.
}
finally
{
    if (reader != null)
    reader.Close();
}

Of course, C# developers can whittle the code down a little more and still be accurate.

(Sorry, Visual Basic folks. The using block doesn't appear in that language until the 2005 timeframe. In Visual Basic 2005, however, you can add this nice implicit behavior to your toolbelt.)

Anyway, back on the bikes, Adam and I continued to argue about this bit of code for an entire week. My theory is that when writing code, developers should constantly ask, for each bit they write, “Is this the best way to write this code? Could I make this more elegant or simpler?” Adam's theory is that most developers don't have that luxury (he's most likely correct) and that just getting it to work is the goal. Therefore, most working developers need rules that are consistent and easy to follow. As such, Adam has posted a series of rules for better .NET development on his corporate site (see the full list at http://www.ssw.com.au/SSW/Standards/Rules/RulestoBetterdotNETProjects.aspx). We may never agree on this one. I'm not sure it really matters, in the long run.

When Adam started asking around to see what others thought (not that he would trust my opinion), pragmatic Paul Sheriff suggested that if developers are focusing on this level of code day in and day out, they're just wasting time. He strongly suggests, and I have to agree, that a better approach is to use a development framework, or a code generator, or a wrapper around common functionality so you're not writing brute force .NET support code all the time. One simple solution would be to download and adopt the Microsoft Data Access Application Block (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/daab-rm.asp), which neatly wraps up much of the grunt work involved in writing applications that use data. I couldn't agree more. (Ed. CODE Magazine features an article describing the Microsoft Data Access Application Block in the Sept/Oct 2004 issue.)

To be honest, I really and truly don't care how iron-fisted Adam rules his “roost” - he can force his developers to do whatever he wants. I think the application block is a great solution, and I'll continue to fixate for far too long on every line of code I write, because I can. All I ask is that Adam doesn't ever make me crawl up Los Angeles' steepest slope again. I want to live to see my retirement years.

(And yes, I know I promised a column covering hashing this time?I got distracted by Adam's plight. It's on the top of the list for next time, really.)