# Thursday, 14 August 2003

You can go home again…


Tonight was a major homecoming, for many reasons. I was born in Flushing, Queens and spent the first 18 years of my life four miles from Shea Stadium, home of the New York Mets. My late Grandfather took me to my first Mets game in May of 1977 (a loss against the San Diego Padres, I still have the ticket.) I also worked for the Mets as a stadium vendor from 1987 to 1994. So I have been to at least one Mets game every year since 1977, and from ’87 to ’94 I must have worked over 500. Tonight was my first and only game of this season. So as my pal Kyle and I traveled on the 7 train to Shea tonight to watch the Mets take on Barry Bonds and the San Francisco Giants it was a bit of a homecoming for me.


But despite what my teammate Tom Halligan says, this blog is not all about me. Tonight was a very special Mets game for Mets fans. Superstar Mike Piazza officially came off the disabled list after missing the last three months of the season. So tonight was Mike’s homecoming and first game as a Met since early May.


Let’s just say that this game was one of the best games ever. I have never seen Mike Piazza hit a home run and most of the games I go to the Mets lose. Not tonight. Mike hit a 2 run home run and two singles for 5 RBIs in his first game back. The place went wild.


In addition to killing the first place SF Giants 9-2 tonight, there was insult added to injury. Pitcher Steve Trachsel hit an RBI double! That never happens non-baseball fans. Steve also pitched 7 2/3 solid innings.


But wait there’s more. Smart ass Barry Bonds (how dare he compare himself to Babe Ruth) had a horrible night. He actually got a hit but was tossed out trying to stretch it to a double. Then in the 8th inning, they pinch hit for him! I think that the last time someone pinch hit for Barry was in 1986.


The only bad point of the game was at the 7th inning stretch when RD Mom Eileen Crain called to tell me that Scott Hanselman and myself are in trouble due to some emails we sent on a private alias. I told her that she should chill out (which made her more mad) and had to call Scott to tell him the deal and then he called her and then I called her when I got home. We all love each other again, but I think it is kind of funny that news can travel so fast, from Redmond, to Flushing to Portland in a matter of 2 minutes without the aid of a computer.


Homecoming was fun and congratz again Mike.

posted on Thursday, 14 August 2003 03:40:28 (Eastern Daylight Time, UTC-04:00)  #    Comments [1] Trackback
# Wednesday, 13 August 2003

Ready for Tech*ED Malaysia


Next Friday I leave for Tech·Ed Malaysia held in Kuala Lumpur. This is the last major conference (and last TechEd) of the year for me.


We have a bunch of Regional Directors speaking:


Adam Cogan (Australia)

Tim Huckaby (US-San Diego)

Clemens Vasters (Germany)

Scott Hanselman (US-Portland)


Looking forward to some geek talk and time in KL with some of the other speakers and RDs. Looking forward to catching up with my buddy Adam Cogan, haven’t seen him since Dallas, far too long. I will get Scott Hanselman to do some drinking this time, no more lame crap from you Scott. Also looking forward to hacking some das Blog with Clemens while in KL (We will party too and his girlfriend, Pat, owes me a favor!)


I just got my machine all ready to go. Here are my sessions, the Stored Procedure session is the last time I talk about The Rozenshtein Method this year (and maybe forever if they let me talk about Yukon next year):

ASP .NET DataGrid Drill Down
Track: Developer Tools & Technologies   Code: DEV203
Room: Tun Dr Ismail A   Time Slot:
Tue, August 26 12:00 PM-1:15 PM
Stephen Forte
The ASP.NET DataGrid is an incredibly powerful and timesaving server control. Compared to "classic" ASP, with just a few lines of code you can load it with data from any data source. Formatting is accomplished by setting just a few properties. Gone are the days where you had to write lots of complex code to filter, sort and page through your data. In-place editing is also a breeze. This session will show you how easy it is to use the ASP .NET DataGrid and accomplish powerful .NET grids without sacrificing any flexibility and functionality.
.NET CF Database Development with SQL Server CE 2.0 ROI

Track: Enterprise Data Management   Code: EDM207
Room: Tun Hussien Onn A   Time Slot: Wed, August 27 4:00 PM-5:15 PM
Speakers: Stephen Forte
The decision to build an embedded application has been made. In today's environment, Return on Investment (ROI) so important that it is now a main decision making factor in deciding what platform to use. Choosing the platform that your developers can leverage their existing skills and code to build something on time and on budget is more important than a cool new language or feature. We will look at a case study of a .NET CF PocketPC application build for Professional NFL Scouts using SQL Server CE 2.0. See the ROI decisions for justifying the development effort, training the developers, leveraging current ADO code and libraries and maintenance decisions along with lines of code comparison to the other embedded tools.

Efficient and Secure Data Retrieval in Your Middle Tier Using Stored Procedures and ADO. NET.

Track: Developer Tools & Technologies   Code: DEV206
Room: Tun Dr Ismail A   Time Slot: Wed, August 27 5:30 PM-6:45 PM
Speakers: Stephen Forte
Using Stored Procedures is more efficient, secure, and easier to maintain than using in-line SQL in your application's middle tier. In this session we will look how to optimize using Stored Procedures for efficient and secure data retrieval in the middle tier of your web, windows, mobile and web services applications.

Using Regular Expressions in Windows Forms and ASP .NET

Track: Developer Tools & Technologies   Code: DEV315
Room: Tun Hussien Onn A   Time Slot: Thu, August 28 10:30 AM-11:45 AM
Speakers: Stephen Forte
Regular expressions, although popular in Perl and other UNIX/C-like languages, are unintelligible to those not familiar with them. Regular Expressions provide an incredibly powerful and compact way of matching and replacing text. Once you become serious about .NET, you'll find Regular Expressions staring you square in the face. They're there and they are very important, but the .NET documentation doesn't help much in learning about Regular Expressions and how to work with them in .NET. This session will introduce you to RegEx, using RegEx as data validation and manipulation.

posted on Wednesday, 13 August 2003 14:46:01 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Tuesday, 12 August 2003

Strategic Inflection Point


Andy Grove, in his bestselling book, Only the Paranoid Survive, describes the nightmare moment every leader dreads--when massive change occurs and a company must, virtually overnight, adapt or fall by the wayside-- a “Strategic Inflection Point.” The arrival of the Internet was one such Strategic Inflection Point in the tech industry. I think that we are at another.


The Strategic Inflection Point is for consulting firms today and the issue is outsourcing off shore. Large companies are outsourcing almost their entire development work offshore. JPMorgan Chase just announced 50% of its IT will now be offshore (that is oh about 4,000 development jobs). I am not going to make the case for or against outsourcing, since it is happening anyway, apparently if you have a convincing argument against is, nobody is listening to it. So why fight it, it is happening and the jobs are not coming back (at least not to New York). This is why I left consulting in July 1999.


But wait, there is still money to be made in the contractor role. First let’s say that you are running a consulting shop today and are feeling the pinch of outsourcing. Let’s look at the notion that it takes 30% of the development effort to design the application, 30% to code, 30% to test and 10% to physically implement.


I always say that the strategic advantage you bring to the table in the 30/30/30/10 universe is the design. That is the MOST important phase of any project-period.  (Don’t make me go Steve McConnell on you!) What if you set up shop to do the 30% design and 10% physically implement?  You can make the case to do the design locally and then work with the outsourcers offshore to code and test. Set up a strategic partnership with several off shore players. Or better yet set up a JV. You can then take on a project management, relationship management and architecture guidance role. I have worked with overseas outsourcing and they tend to follow specs to the letter, so if your potential customer has made the decision to outsource overseas, they will be more inclined to do the design work very seriously.


Just an idea…

posted on Tuesday, 12 August 2003 20:24:02 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback

Mount Rainier called a threat

What were we thinking?


posted on Tuesday, 12 August 2003 02:20:22 (Eastern Daylight Time, UTC-04:00)  #    Comments [16] Trackback
# Monday, 11 August 2003

The age old question. If you ever saw one of my TechEd sessions or WebCasts, you know that I am a big fan of using the DataReader, especially when you are doing Web DataBinding. I am all about the firehose, forward only cursor. Today I actually replaced a DataReader with a DataSet, so I think that I need to tell the world the story. J


So my app that runs each Sunday morning to get data over HTTP and regex out stuff was bogging down. What happens is that I have a DataReader on the client that grabs the URLs, RegEx patterns, etc from a table for the main application “loop” to process the URLs and save the data to the database. There are about 30,000 records stuffed into the datareader and the stored procedure that powers it has to do a join to the table I am adding data into on each iteration of the loop to make sure that if the process stops and restarts, I don’t reprocess any duplicate URLs.


So all of a sudden (this code has been in production for 15 months, and on .NET 1.1 for 4 months) I started to get timeouts when I read data from the DataReader. Randomly this would happen, maybe once ever few weeks. I never really tracked it down. So this week I would run the process and every 10th record would cause a timeout. It was a timeout when I tried to read data from the next row in the DataReader, on the 10 row. I start and stop and this happened a zillion times. I spent a few minutes playing with some settings, etc, but more of the same. Oddly enough, setting the command behavior of the command that filled the reader to SequentialAccess did not even let me read data from the first record, it returned an error saying that it can only look at data starting at the 10th row.


I have not discovered the problem here, but it must have something to do with the buffer, I must have been stuffing way too much data in there. So I said DUH, let’s use a DataSet. Well I never looped through a DataTable before, so here is how it goes:


Private void DataTableLoop (DataTable dt) {


   foreach (DataRow dr in dt.Rows) {

      foreach (DataColumn dc in dt.Columns) {

         Response.Write (dr[dc] +”





posted on Monday, 11 August 2003 15:54:28 (Eastern Daylight Time, UTC-04:00)  #    Comments [4] Trackback


That was my triathlon time today! I am very happy. Teammate Andy Catlin got out of the water a few seconds before me (we both were at 15 minutes) and we had a hard transition (lots of rocks, and the bikes were far from the water). The bike was brutal (55 minutes). Almost all uphill, about 75% of the bike was uphill.  We had a 4 mile downhill at one point that was so super steep hill-I hit 47 miles per hour! That is almost as fast as a car… Transition from bike to run was not that bad. The run was hard, but ok, about 25-26 minutes. Andy finished about 5 minutes behind me, way to go dude…

posted on Monday, 11 August 2003 02:19:29 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Saturday, 09 August 2003

Radio Uninstalled

Radio is completely off my machine. This is good since it was slow and clunky.

This is a day of liberation for Clemens and I. We are now using our Radio subscriptions just to upstream our RSS feeds to the Userland cloud dasBlog. Very cool. So now all the folks who have not resubscribed can still see the feeds at Radio, but please please please subscribe to the new feed.

What is funny is the Clemens said he did not have enough time to document everything, but his documentation is much better than Radio's! Besides my forthcoming cache code contribution to dasBlog, I have to say that Clemens rocks the house, so buddy, I owe you a few beers when we are in KL next week speaking at Tech·Ed Malaysia.


posted on Saturday, 09 August 2003 23:17:06 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback

Taper Day


Today I do nothing but sit at home, drink drink drink water and eat pasta. Tomorrow is the big race.

Last night I went out with some buds, including Rob Wlodarczyk who leaves for a job at the Evil Empire on Tuesday.

posted on Saturday, 09 August 2003 18:42:06 (Eastern Daylight Time, UTC-04:00)  #    Comments [2] Trackback
# Friday, 08 August 2003

Overcome Parkinson's Law


Parkinson’s Law is taking over. The basic thesis of Parkinson is: ‘Work expands so as to fill the time available for its completion.’


So I have called a meeting to discuss 1 small bug, should take 5 minutes, but call the meeting for 30 minutes. The meeting will last 30 minutes!


Further explanation from Parkinson:


“General recognition of this fact is shown in the proverbial phrase 'It is the busiest man who has time to spare.' Thus, an elderly lady of leisure can spend the entire day in writing and dispatching a postcard to her niece at Bognor Regis. An hour will be spent finding the postcard, another in hunting for spectacles, half an hour in a search for the address, an hour and a quarter in composition, and twenty minutes in deciding whether or not to take an umbrella when going to the pillar box in the next street. The total effort that would occupy a busy man for three minutes all told may in this fashion leave another person prostrate after a day of doubt, anxiety, and toil.”


So this has a lot to do with being efficient. Overcoming Parkinson’s Law is one the most liberating things that you can ever do. A big problem I have with meetings today in corporate American. They last forever and never accomplish anything. I hate when someone calls a meeting and there is no clear reason for it and then says “Stephen why don’t you start off the meeting.” Argh. So I put an end to this. Now my new rules for meetings are (and if they don’t meet this criteria, I don’t attend the meeting, unless the person calling the meeting is “important” J):


1.         No meeting lasts more than 45 minutes

2.         All meetings are "stand-up" meetings, nobody sits down

3.         There are no meetings without an agenda

4.         No meetings should have any food or drink allowed in them

5.         No meetings at odd hours: 5pm, obvious lunch times, etc


When I was CTO over at Zagat, I also instituted a meeting free Friday, something that you may want to try at your place too. I got away with it by sending an all day meeting invite to my entire staff called “Staff Meeting” that had a recurrence on every Friday and then when other people used Outlook/Exchange to schedule a meeting, they were always booked on the Friday!!!


Even if you can’t control the 5 items above, you can always ask the meeting organizer to circulate an agenda before the meeting, this will get them thinking more efficiently!

posted on Friday, 08 August 2003 14:32:11 (Eastern Daylight Time, UTC-04:00)  #    Comments [19] Trackback

Up with das Blog 1.1!

I am now up. If you are upgrading from 1.0 to 1.1, make sure you read the notes.

Time to work on the cache engine, Clemens has challenged me :)

[08:32] Peakbagger: :I am up now dude. :)
[08:32] Clemens (viel zu warm!): should work much better
[08:32] Peakbagger: looks pretty smooth
[08:33] Clemens (viel zu warm!): now... make it faster
[08:33] Clemens (viel zu warm!): ;)
[08:34] Peakbagger: that I can do


posted on Friday, 08 August 2003 12:51:22 (Eastern Daylight Time, UTC-04:00)  #    Comments [13] Trackback
# Thursday, 07 August 2003

I have to admit that I am totally hooked on the The Rozenshtein Method. My buddy, Richard Campbell showed it to me a year or two ago and I have been hooked ever since. I recently demoed it at TechED in Dallas, a recent WebCast, VSLive in New York and will be showing it off at TechEd in Malaysia next week. I have gotten lots of email and positive feedback so I decided to blog it here.


Here is how it works. You need a crosstab query.  You have to move rows into columns. You also need ANSI 92 SQL that will run in any database.Well there are several ways to do this, but the most generic and one of the most powerful ways is called the Rozenshtein Method, which was developed by the Russian mathematician David Rozenshtein. This technique was taken from his book: Optimizing Transact-SQL : Advanced Programming Techniques.


First let’s look at the desired results. We want to take the orders data from Northwind and pivot the sales date (aggregated by month) as columns with the sum of the total sales in the row grouped by customer. It would look something like this:


CompanyName TotalAmount Jan Feb Mar…(etc)

Company1        100              25 33   10

Company2           467                 76 62    87



The TSQL query to do this is, go ahead and run it in Northwind in SQL Server:


SELECT  CompanyName, SUM((UnitPrice*Quantity)) As TotalAmt,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-1)))) AS Jan,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-2)))) AS Feb,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-3)))) AS Mar,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-4)))) AS Apr,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-5)))) AS May,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-6)))) AS Jun,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-7)))) AS Jul,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-8)))) AS Aug,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-9)))) AS Sep,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-10)))) AS Oct,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-11)))) AS Nov,

  SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-12)))) AS Dec

FROM         Customers INNER JOIN

                      Orders ON Customers.CustomerID = Orders.CustomerID INNER JOIN

                      [Order Details] ON Orders.OrderID = [Order Details].OrderID

Group By Customers.CompanyName


So how does this work?


This method uses Boolean aggregates, so that each column has a numeric expression that resolves each row as a zero or one and that value (0 or 1) is multiplied by your numeric expression (Like TotalSales or (UnitPrice*Quantity). That is all there is to it, quite simple. But wait, there’s more to explain:


We want to create columns for each Month in our data. To find a month use DatePart. But we need to subtract the DatePart value (1-12) from the amount you’re looking for (1 for Jan, 2 for Feb, etc) as shown here for January:



So that true = zero, false > 0 or < 0. For example if the month you were looking for was January and the DatePart was 1 and you subtract 1 from that value you get 0, which is true. If you are looking for March you would get -2 and that would be false.


Next you have to compute the sign of the expression and get the absolute value like so:



This will give us a positive value. Remember 0 is still true. Now subtract the value computed from 1 in order to get a 0 or 1 from the value of your expression (the Boolean aggregate). The code is:



For example if you had March return 3 from the Datepart, 3-1=2 and 1-2 =-1. The absolute value is 1. This will always return 0 or 1. If your expression was zero, the value is now one. If was one, the value is zero.


Last step. Taking the SUM of the Boolean values will give you a count of the values that qualify. So you can find out how many sales you made in Jan, Feb, etc. So now multiply the value by the price and quantity, but remember its now one = true. Take a look here:


SUM((UnitPrice*Quantity)*(1-ABS(SIGN(DatePart(mm,OrderDate)-1)))) AS Jan


If its zero, nothing gets added, if its one, you get the value of the sale. The sum of the total expression is the total of sales for the month. If you have a DatePart that is evaluated to 0 then ((UnitPrice*Quantity)*0) is 0 and those results are ignored in the SUM. If you have a month that matches your expression resolves to 1 and ((UnitPrice*Quantity)*1) is the value of the sale.


How easy!


But wait, there’s more! Suppose you wanted two values combined? Compute each value down to zero or one separately. Now you can use AND by multiplying, OR by adding (and reduce to 1 or 0 using SIGN).


Ok, have fun!!!

posted on Thursday, 07 August 2003 08:38:37 (Eastern Daylight Time, UTC-04:00)  #    Comments [7] Trackback