Tuesday, October 05, 2004

Sorry for the non-technical post, but I must agree with Sam Gentile.  I saw Sky Captain and the World of Tomorrow on opening weekend and thought it was a blast.  I couldn't precisely nail down what I liked about it, but I think Sam hits the nail on the head: it's a mixture of (semi-)modern sci-fi with a Flash Gordonesque, 30's style.  I absolutely love the pastel, sepia color used throughout the flick.  I am definitely one for nostalgia, and watching this movie I felt once again like a kid.  Watching the characters travel over the globe with the super-imposed lat/long lines and compass beneath the surface of the water was fantastic; that and the abnormally enlarged radio tower summoning Sky Captain...Watching it reminded me too much of the old George Reeves Superman...though the movie wasn't that corny.

I normally wouldn't be posting something like this, but it turns out that during my weekly programming session with a group of friends last night we were talking about just this movie.  Then reading Sam's blog I couldn't help it.  Go see the movie if you haven't yet!

Tuesday, October 05, 2004 7:45:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, October 04, 2004

By no stretch am I an Xml guru.  I know enough to get by and can be pretty dangerous with it.  I stumbled upon this tool by Jeff Key that I find extremely useful.  I deal with a lot of XML as single, long strings.  I want to view the Xml in a hierarchical node-tree view and while IE gives me that (to a limited degree), this tool gives me much more power with a very small learning curve.

  • You can view your Xml loaded from a file
  • You can view your Xml loaded from the clipboard.  Nice!  While this functionality might be expected, I'm glad the Jeff took the time to support such functionality.
  • Organizes your Xml indented (regardless of whether it came in in that format or not)

Now if you're wanting more power and capabilities, but at a steeper learning curve, there is also the XMLSpy 2004 Home Edition (which is free) or the Professional or Enterprise versions.

Unless I absolutely need the added functionality, though, I'll be sticking with Jeff's tool...thanks Jeff!

Request:  Support XPath queries for searching; it would help facilitate using a single tool for my basic XML needs, rather than having to jump between tools to perform those queries.

As you can see, sometimes the simplest of things gets me excited because I've been wanting this capability for a long time, but haven't taken the time to write it myself.

Monday, October 04, 2004 8:47:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Saturday, October 02, 2004

I consider myself a pretty good ASP.NET developer.  However, it doesn't matter how many times I try to do it, I can't seem to remember how each of the path functions on the Request and Page/Control objects work.  Invariably I find myself opening MSDN or tediously debugging and stepping through my code, making heavy use of the Command Window or the Quick Watch dialog.

Thanks to Rick Strahl for consolidating these functions in a manner that's easy to read and understand. :-)

Saturday, October 02, 2004 3:54:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, September 30, 2004
I was catching up on some blog reading and ran across this link in Eric Gunnerson's C# Compendium.  Great game that tests your ability to not follow your instincts.  Fantastic game!
Thursday, September 30, 2004 4:07:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback

If you're a website developer you may have run across several of the nuances presented with the more secure IE 6 for Windows XP SP2 - namely the Information Bar (the nice yellow bar that appears at the top of the webpage when the page attempts to perform some restricted action such as display a popup the user didn't request, or the unsolicited installation of an ActiveX control).

Here are a couple of great links to follow to learn more about those restrictions and how to make your website play friendly in their new environment:

Compatibility in Internet Explorer 6 for Windows XP Service Pack 2

Fine-Tune Your Web Site for Windows XP Service Pack 2

Thursday, September 30, 2004 3:50:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, September 29, 2004

Last night I was greeted to a very unpleasant, and unsettling occurrence that had me baffled until today when I got some help from a great friend - one of my old co-worker buddies from Microsoft.  My network was up and everything was fine (internally), but I couldn't get any DNS resolution outside my network (i.e. out on the internet).

As it turns out I could ping my router from every computer on the network except my domain controller (which is also my DNS server).  Because my DNS server couldn't resolve anything, I was pretty dead in the water.  I tried several things to fix the issue, but nothing worked.  It was suggested by my buddy to change the server's IP address and see if I couldn't still ping the router.  Lo and behold that was the problem!

Somehow, somewhere, the router was denying traffic from my old IP address.  Without any concrete evidence, I attribute this problem to a pretty bad power outage that we had a few days ago.  Even after powering down the router for several minutes and starting it back up I could not get connectivity on the old IP so I had to resort to a new IP.  Crazy, but at least it works!

Ya know? I've been in the contemplating getting a new, good, reliable router anyway...maybe this is the incentive that I need.  This one that I have (a NetGear) has been fantastic over the past several years, but I've been wanting to get something newer and better; budget is not the primary concern - but practicality is.

Any suggestions?

Wednesday, September 29, 2004 3:24:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [3]  |  Trackback
 Monday, September 27, 2004

Today I had an issue in which I wanted to build out a tree of data.  This information is collected in a single table with self joins to define the hierarchy.  I wanted to avoid having to repeatedly query the database for a subset of the records - instead, I wanted to get the whole batch from the database, already organized and set up in the tree.  I've done things such as this in Oracle via the CONNECT BY statement in the past, but unfortunately SQL Server (in its current incarnation) doesn't support this type of functionality; therefore, I had to resort to rolling my own.

A join (either OUTER or INNER) did not give me what I wanted, though the relationship could be established, so I decided to write a stored procedure to accomplish this.  Now, to be honest, I have not profiled this to see how it can be optimized (I'd welcome insights regarding that) but for small set of data (e.g. < 10,000 rows) I think this approach might work reasonably well.

Basically, the idea is that the stored procedure establishes two temporary tables: one for the final output and one for the work in progress.  You can call the procedure, indicating the root node for the hierarchy (defaulting to the top - those items that have no parent; identified by NULL).  From that point, the procedure begins to analyze the data, writing into the temporary work table (called #Stack) and recording records as necessary into the #Output table.

My strategy (as this will be used in a web-based application and will rarely, if ever, change) is to query it once and cache it so I don't have to perform this analysis over and over again.  Additionally, I'm really only expecting < 50 records so the hit is pretty minimal.  What do you think of the approach?  Good?  Bad?  Ugly?  Ingenious?  Mediocre?  I'd be interested in getting some good feedback.

CREATE PROCEDURE dproc_GetCategoryList
   @RootParentID int = NULL
AS
   SET NOCOUNT ON

   -- establish the table that will contain the output results
   CREATE TABLE #Output ( ID int, Name nvarchar(35), ParentID int )

   -- establish the work table
   -- this data will fluctuate and will represent the information that is being processed
   CREATE TABLE #Stack ( ID int, Depth int )

   DECLARE @currID int
   DECLARE @depth int

   IF ( @RootParentID IS NULL )
      -- start at the parent level (there might be multiple top-level parents) and start working our way down
      -- top-level parents are identified by not having parent themselves
      DECLARE topLevel CURSOR FOR
      SELECT ID FROM tblCategoryIndex WHERE ParentID IS NULL ORDER BY Name
   ELSE
      -- start at the level prescribed by the caller and build out the child hierarchy
      DECLARE topLevel CURSOR FOR
      SELECT ID FROM tblCategoryIndex WHERE ID = @RootParentID

   OPEN topLevel
   FETCH NEXT FROM topLevel INTO @currID
      WHILE ( @@FETCH_STATUS = 0 )
         BEGIN
         SET @depth = 1
         INSERT INTO #Stack VALUES ( @currID, @depth )

         WHILE ( @depth > 0 )
            BEGIN
               IF EXISTS ( SELECT ID FROM #Stack WHERE Depth = @depth )
                  BEGIN
                     -- read the next record's id for processing so we can get its children and delete it
                     SELECT @currID = ID FROM #Stack WHERE Depth = @depth
                     DELETE FROM #Stack WHERE Depth = @depth AND ID = @currID

                     -- add the category to the output table
                     INSERT INTO #Output SELECT ID, Name, ParentID FROM tblCategoryIndex WHERE ID = @currID

                     -- get the children of the current category
                     INSERT INTO #Stack SELECT ID, @Depth + 1 FROM tblCategoryIndex WHERE ParentID = @currID ORDER BY Name DESC

                     IF ( @@ROWCOUNT > 0 )
                        SET @depth = @depth + 1
                  END
               ELSE
                  -- move up one level, we're recursed as deep on this node branch as we can go
                  SET @depth = @depth - 1
            END

         FETCH NEXT FROM topLevel INTO @currID
      END
   CLOSE topLevel
   DEALLOCATE topLevel

   SET NOCOUNT OFF

   -- return the result set
   SELECT * FROM #Output
GO

- [Updated 09/28/2004 for proper sorting of the name - the list is now properly alphabetized in the result set.]

Monday, September 27, 2004 8:40:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Friday, September 24, 2004

For all those programmers out there that think that it's important to write code that is easily maintainable, think again!  You want job security, right?  Think about yourselves for a change - be selfish!  It is of utmost importance to create code that is not only unmaintainable by the unsuspecting inheritor of your code, but if you have to spin your wheels going back over something you just wrote - all the better - it'll keep you employed and your boss will think that you're worth every penny by solving these insurmountable problems found in the mazes and jungles of code!

For more details, check this site out.

Friday, September 24, 2004 11:20:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Thursday, September 16, 2004

I've been debugging this issue (or rather, attempting to debug this issue) wherein I have some ASP.NET controls that perform postbacks.  These controls are of my own make and are UserControls (.ascx).  Ages ago I thought I'd be clever and set the the EnableViewState property of the page to false because the information I'm presenting rarely (if ever) changes.  I query it once and cache the data and redisplay it on round trips to the server - not a big deal.

...until I decide to put a DataList on the control and want to capture the ItemCommand event on items within the list.  It turns out that unless the Page has EnableViewState set to true, the control events don't get wired up properly.  Now I've seen this behavior before and I've known about these circumstances from eons ago, but it's funny the little things you forget in an attempt to be clever.

Thursday, September 16, 2004 7:56:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback