CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Brendan Tompkins [MVP]

Blog First. Ask Questions Later.

April 2004 - Posts

  • Book Review: Coding Slave by Bob Reselman

    Reading for pleasure is one of those things that I seem to do less than I’d like. One of the big reasons is that I’m a reading adrenalin junkie. I’ve done this to myself. For a long time, I’d read nothing but those catastrophe at sea, stranded on the top of a mountain, dying in the forest, non-fiction books. It’s embarrassing, but I’ve gotten so that if the main character doesn’t stave off starvation by eating their recently-dead best friend for lunch in the middle of the southern ocean with no hope of survival, I’m not really interested. And that’s just non-fiction. If it’s fiction, it’s got to be even more shocking to keep me interested. If someone "made up" the story it better be about sex-crazed junkie bank robbing circus freaks, staving off starvation by eating their recently-dead best friend for lunch in the middle of the southern ocean.

    Well, that being said, I tore through Coding Slave. Something about it just clicked with me. It’s funny, but in a way it’s very similar to these catastrophe at sea books. Only that the catastrophe is the current state of software development and we’re all in the same boat.

    Coding Slave describes, very accurately, what happens to us as software developers. The cast of characters is great: a decadent, over-paid jet-setting consultant, a true coder struggling to fit into the corporate coding environment, and a brilliant highly educated foreign-born female engineer willing to do anything for her clients.

    Everything happens in this book. There’s a murder. A suicide. A murder-suicide. Sex. Scandal. The FBI. More sex. It’s just great.

    But that’s not the point at all. The entire book, in a way, is a stage for Reselman to tell you his vision for how to fix the current mess in our profession : broken software, budget overruns, redundant efforts, poor quality of life, lack of respect, imposters, un-equal compensation, under-compensation: the whole nine.

    I’m an idealist. So’s Reselman. I think It’s good to be an idealist, but then again, and idealist would. So suffice it to say, I’m totally into the ideas he has for us in Coding Slave. I’m going to go out on a limb and say that Coding Slave is the Walden of the modern age. Okay, maybe it’s more like Skinner’s Walden Two, than Thoreau’s Walden. But it does propose a utopia of sorts. So the question becomes, could the utopia proposed in coding slave work?

    Well, people have tried to implement Skinner’s ideas from Walden Two, and they work, um sort of, but you don’t see us all working four-hour days and spending the rest of our time painting. I, for one, would like to try out Reselman’s ideas.  Then again I’d go live in Walden Two: I’m an idealist.

    Now, the book’s too good to get nitpicky about style. Stylistically, Kurt Vonnegut comes to mind, a little too much at times. Perhaps this is just coincidence. But, then again I love Vonnegut. It’s kinda like this book was tailor made for me.

    My one big gripe is that the book literally fell apart twice on me. The binding sucks. It’s slapped together with that plastic ring binding we use for code docs. Perhaps this was intentional. This was annoying because I had to stop reading to re-assemble the darn thing. Well, hopefully the next printing will be perfect bound.

    So, can you tell I liked it? .

    -Brendan

  • Spring Blog Cleaning

    So, today I decided to clean up my blog. It is spring, after all.  I created a bunch of categories that made sense to me at the time.  Here they are:

  • Active Directory (rss)
  • ASP.NET Patterns (rss)
  • ASP.NET Tidbits (rss)
  • ASP.NET Tutorials (rss)
  • C# Language & Syntax (rss)
  • Mobile .NET (rss)
  • Offshore Outsourcing (rss)
  • SharePoint (rss)
  • Software Consulting (rss)
  • SQL Server (rss)
  • Visual Studio .NET (rss)
  • Good for me. :)

    -Brendan

  • Transform an ADO.NET DataSet to ADO Recordset XML, Excel XML and more!

    A couple of weeks ago, I complained about the KB code here KB316337.  What this code is supposed to do is transform a DataSet into ADO Recordset XML format.  I ended up porting the VB code to C# and also rewriting some of the code along the way...  It's too much code to show it all here so I've created a web project that you can download which contains the transformation in a utility class.

    Using this utility class you can transform a DataSet into different formats, including ADO Recordset XML, Comma Delimited, Tab Delimited and Excel XML.  Others have posted about doing the same thing, notably Darrell Norton in a post here.   I've boiled it all down in to an easy to use utility class.  To use this, simply make the method call like so:

    Util.ExportUtils.ExportDataSet(this.exampleDataSet1, "ADOXMLExport", Common.DataSetExportType.ADORecordSet, this.Context);

    Notice that the third parameter is an enumeration specifying the export type. This enum looks like this:

    public enum DataSetExportType
    {
       XML,
       ExcelXML,
       TabDelimited,
       CommaDelimited,
       ADORecordSet
    }

    Why would anyone want to go from ADO.NET DataSet to an ADO Recordset?  Well, one big reason is to funnel  a .NET DataSet's data into an Office Web Component, such as a PivotTable and PivotChart.  This can be pretty powerful stuff. The example page included in the project lets you go from a DataGrid bound to a typed dataset, that looks like this:

    To a Pivot Chart that looks like this:

    Trust me, show this to a client and they'll do backflips with excitement!

    If you're intereseted in seeing all of this in action, download and run the project here.  Don't open the ASPX page with the designer, because it messes up the <OBJECT> code for the OWCs. Also, to use the OWC, you'll need Office XP and you'll have to trust your local domain from within IE's trusted sites tab.  This was (quickly) thrown together for example purposes, so you may have to tweak it for your specific implementation, but it should get you started. Enjoy!

    -Brendan

     

  • I'm Confused: Michael Moore Outsourcing?

    My good bud Mark DiGiovanni just IM'd me this link.  Can it possibly be true?   Okay. Canada,  Well, that's not Bangalore, I know, but its not US either.  Is it really that different from sending work to India?

    I've always thought is that wherever you are, you should support locally owned busniesses wherever possible.  Yes, I'm one of those people. To me it comes down to this: When you buy your coffee at a privately-owned company based in Washington state you are funneling money out of your local economy to another part of the country.  This means less local money to support the local economy.  This is what Michael is doing, in a sense.

    So Michael,  I know you're from Michigan, and the difference between US and Canda can  get a little confusing up there, but what gives?  Now I really need to call you.

    -Brendan

  • Goodbye CodeSmart, Hello CodeRush!

    OBSOLETE CONTENT
    The author of this post has determined that this content is obsolete. Use at your own risk! Blog posts are a point-in-time snapshot of the blogger's thinking and should not be assumed to represent this blogger's current opinions. This post was left up for historical purposes.

    Wow.  Via Rory's blog, I came across a new Visual Studio tool, CodeRush.  I installed a copy this morning, and I'm doing backflips!  I won't go into all of the features, but anyone writing code will immediately see coding speed gains.  Best of all, I got to finally uninstall my copy of AXTools CodeSmart, which on my machine was doggedly slow and buggy. Sorry AXTools, but I gave you a year to sort out your issues, and you didn't come through for me. I was hanging on to CodeSmart for one or two features, and CodeRush gives me those features, and much more....

    -Brendan

  • Auto Event Wire-Up for Controls

    Ever noticed that when you double-click on an ASP.NET UserControl, the code-behind loads, with the cursor in the Page_Load event?  Well, this as far as I can tell, is because the UserControl class contains a DefaultEvent attribute, specifying “OnLoad“ as the event.  Thus, the VS IDE automatically wires up this event and writes the skeleton code below for you:

    private void Page_Load(object sender, System.EventArgs e)
    {
    }

    Problem is, I don't want my UserControls to tell my IDE to do this for me. This is because I generally don't think it makes good design sense to use the Page_Load event  from a UserControl.  If you've developed ASP.NET apps with multiple controls on a page, you know what I mean.  Your app logic may be hiding/showing controls ala Dave Burke's post here.  Wheneach UserControl is doing something on Page_Load, things get done too often, and often unnecessarily.  Actually, I often delete this method all togtehter. What makes more sense is to have an OnVisible event or  what I've done is added a Show() method stub to my UserControlBase class that is intended to handle the initial setup stuff. 

    So when I double click on the designer panel, I don't want the Page_Load method to be added and wired for me. This is annoying when I've deleted it.  One thing I can do is create an Attribute for my base class specifying and “OnVisible” event if I had one or any other event for that matter.  But what if I don't want any event wired up?  Does anyone know how to keep the IDE from autmatically wiring up events for a class? 

    -Brendan

  • Other Risks of Off-Shoring?

    I'm feeling much better about the off-shoring issue lately.  For one thing, Newsweek had a big article last week highlighting some big offshore failures, and some evidence of on-shoring.  But, really interesting is Rory Blyth's take on what could happen to your off-shored data in countries that are less-than-secure.  Could you data be blown up by terrorists, taken hostage, or worse?  Very interesting stuff.  And in the comments, there's this link describing one scenario where this actually happened!  Yikes!

    This all leads me to wonder, could an application's security be compromised the same way without the end-customer knowing?  Could developers be coding in obscure back-doors that are hard to find?  If you're thinking “That could never happen, someone would find it.” ask yourself this question: What are the chances that your end-client would discover a back door that you wanted to hide?  Now, agreed, this can happen anywhere, including in the US, but is there a greater risk if a project is off-shored? 

    -Brendan

  • Getting the most out of System.DateTime

    First of all, I have to proclaim my love for the System.DateTime and System.TimeSpan object.  I have to say that other than System.Data.DataSet family of objects, they're my favorite.  The thing I like most, is that they give you just enough to usefully and easily extend the functionality, without being bloated and hard to understand.  A sincere thanks to the people involved in making them easy to use.

    As an example, I needed recently needed a bunch of  date calculations, like WorkWeekStart, WorkWeekEnd, etc.  I came up with the following enum and method which I can use to derive all sorts of date caluclations:

    public enum DateDirection
    {
       
    Forward,
        Backward
    }

    public static DateTime GetDay(System.DayOfWeek dayOfWeek, int numberWeeks, DateDirection direction, bool dayEnd)
    {
       
    // Get the initial date.
       
    DateTime checkDate = DateTime.Today;

       
    // If today's not the day we're looking for, loop and find the date
       
    if(!(checkDate.DayOfWeek == dayOfWeek && numberWeeks == 0))
        {
           
    int i = 0;
           
    // Loop for number of weeks...
           
    do
           
    {
               
    // Go forward or back one day..
               
    checkDate = (direction == DateDirection.Backward) ? checkDate.AddDays(-1) : checkDate.AddDays(1);
               
    // Loop until we find the correct day
               
    while(checkDate.DayOfWeek != dayOfWeek) 
                {
                    checkDate = (direction == DateDirection.Backward) ? checkDate.AddDays(-1) : checkDate.AddDays(1);
                }
            }
    while(i++ < numberWeeks); // Loop for the number of weeks.
       
    }
        
       
    // If we need the end of the day, add the ticks to get us there.
       
    if(dayEnd) checkDate = checkDate.AddTicks(System.TimeSpan.TicksPerDay - 1);
       
    return checkDate;
    }

    Using this one method, I can derive all sorts of date calculations, like so:

    /// <summary>
    /// Start of week is Sunday 12:00 am
    /// </summary>
    public static DateTime WeekStart
    {
       
    get { return GetDay(DayOfWeek.Sunday, 0, DateDirection.Backward);}
    }

    /// <summary>
    /// Saturday at 11:59:59
    /// </summary>
    public static DateTime WeekEnd
    {
       
    get { return GetDay(DayOfWeek.Saturday, 0, DateDirection.Forward, true); }
    }

    Ever tried doing this sort of thing with other frameworks?  Uggh!  The ease with which I was able to do this, was really one of those things that makes me a true-beliver in the .NET framework.

    -Brendan

  • Reason #1 to support On-Shore Software Engineering

    Because every once in a while, American developers come up with something as great and important as this.

    -B

  • Off Topic: Compulsive Domain Name Registration

    The other day, I got into a political conversation with a friend, where we decided we could understand where we stand on any political issue with one catch-phrase :

    Legislate Humanity not Morality

    In hindsight, it's fairly simplistic and short-sighted to think that anything complex can be boiled down into a catch phrase, but at the time, it seemed all encompassing.   The funny thing was, I got so excited, I rushed home, and in about 1/2 an hour, registered legislatehumanity.org and put up the following site, where people can print out a bumper sticker if they so choose, and slap it on the back of their old rusty Volvo.

    All this was thanks to Go-Daddy.  They've made the process of putting up sites so easy, that I could see myself getting a bad habit of compulsively registering domain names.  Do I have a problem?  Not yet, but I'm keeping an eye on it.  In fact, I may just register compulsivedomainnameregistrationsupport.org later on today. 

    -B

  • Multi-Table DataSet with DataRelations from a Single-Table DataSet

    Recently, I was tasked with creating a reporting application that did the following:

    1. Allow the user to choose Columns in one DataTable in a DataSet to group by.
    2. Render a grouped report from the flat table data.

    So, for example, if the DataTable looked like this:

    Department EmployeeID Product Count
    Purchasing 3322       Apples  1
    Purchasing 3322       Oranges 1

    Purchasing 3311       Oranges 2
    HR         1222       Apples  1
    HR         1111       Apples  3

    I had to generate a rollup report that looked like this:

    Department: Purchasing
      Employee: 3322
        Product: Apples  Count: 1
        Product: Oranges Count: 2
                         Total  3
      Employee: 3311
        Product: Oranges Count: 2
                         Total: 2
              Purchasing Total: 5

    Department: HR
      Employee: 1222
        Product: Apples  Count: 1
                         Total: 1
      Employee: 1111
        Product: Apples  Count: 3
                         Total: 3
                      HR Total: 4
                   Grand Total: 9

    You can see that the solution was going to involve recursion of some sort.  The trouble was, recursion on a flat DataTable is a nightmare!  If you've ever tried it, you know what I mean. Forget using foreach, and bone up on arrays if you're going down this route.

    Well, I wrote the code to do this recursion, but I wasn't happy with what I had come up with.  It was ugly code, and hard to follow.  I was complaining to a friend of mine about the complexity, and drawing on a white board.  I drew a picture of an ADO DataSet with DataTables related with DataRelations, and said “If I only had this, this would be easy”...  Then it hit me.  I needed to generate a multi-table DataSet from a flat, one-table DataSet.  I could then use the GetChildRows() method of each data row to find out if I needed to recurse. I could also use a foreach to iterate through the DataRows. 

    What I came up with is the following method, that I thought I'd share.  What it does is take a flat DataSet with one DataTable and a string array of ColumnNames that are to be used to generate a DataSet with multiple, related dataTables.  It returns the root table name, which you'll need to start your recursion:

    public static string GetNestedDataSet(DataSet flatDs, ref DataSet nestedDs, string [] columnNames)
    {
       
    string rootTableName = null;
        nestedDs = flatDs.Copy();
        DataTable dataTable = nestedDs.Tables[0];

       
    // Store the previous iteration's previous columns
       
    DataColumn [] prevUniqueColumns = null;

       
    foreach(string columnName in columnNames) 
        {
           
    // Add the table
           
    DataTable tbl = nestedDs.Tables.Add(columnName + "Table");
           
    if(rootTableName == null) rootTableName = tbl.TableName;

            // Store the current iteration's columns
           
    ArrayList currentColumns = new ArrayList();
           
    if(prevUniqueColumns != null)
            {
               
    // Add all the previous columns
               
    foreach(DataColumn col in prevUniqueColumns)
                {
                    currentColumns.Add(
    new DataColumn(col.ColumnName));
                }

               
    // Add the current Columns
               
    DataColumn [] foriegnKeyCols = (DataColumn []) currentColumns.ToArray(typeof(DataColumn));
                tbl.Columns.AddRange(foriegnKeyCols);

                // Add the parent relations
                tbl.ParentRelations.Add(prevUniqueColumns, foriegnKeyCols);
            }

            // Now add the new column
           
    currentColumns.Add(tbl.Columns.Add(columnName)); 

           
    // Get the key columns for the current table
           
    DataColumn [] primaryKeyCols = (DataColumn []) currentColumns.ToArray(typeof(DataColumn));

           
    // Make everything unique
           
    tbl.Constraints.Add(tbl.TableName + "_unique", primaryKeyCols, false);

           
    // Store columns for next time...
           
    prevUniqueColumns = primaryKeyCols;

           
    // Now add the data...
           
    foreach(DataRow row in nestedDs.Tables[0].Rows)
            {
                   
    try
                   
    {
                           
    ArrayList al = new ArrayList();
                           
    foreach(DataColumn c in primaryKeyCols) al.Add(row[c.ColumnName]);
                            tbl.Rows.Add((
    object[]) al.ToArray()); 
                    }
                   
    catch(System.Data.ConstraintException){}
            }
        }
        
        
    // Finally, add the table relationship to the base table
        
    if(prevUniqueColumns != null)
        {
           
    // Add the current Columns
           
    DataColumn [] foriegnKeyCols = new DataColumn [prevUniqueColumns.Length];
           
    for(int i = 0; i<prevUniqueColumns.Length; i++)
            {
                    foriegnKeyCols[i] = dataTable.Columns[prevUniqueColumns[i].ColumnName];
            }
            dataTable.ParentRelations.Add("BaseRelation", prevUniqueColumns, foriegnKeyCols);
        }

        // This happens when we have no rollup columns
        
    if(rootTableName == null) rootTableName = dataTable.TableName;
        
    return rootTableName;
    }

    Now, to use this, do the following:

    DataSet nestedDataSet = null;
    string rootTableName = GetNestedDataSet(MyFlatDataSet, ref nestedDataSet, string [] {“Department“, “EmployeeID“, “Product“});

    Here's an example (warning: Air Code) of the recursive routine to do the rendering:

    private int RenderGroup(DataRow parentRow)
    {
          // Render out something here, like parentRow[0]

         // Now get the children rows, if any and recurse
          
    DataRelation childRelation = (parentRow.Table.ChildRelations.Count > 0) ? parentRow.Table.ChildRelations[0] : null;
         
    if(childRelation != null)
             foreach(DataRow row in parentRow.GetChildRows(childRelation))
                RenderGroup(row, showDetail, container);
    }

    That's it!  I put this method in my Utils class for ease of use.   I hope that posting this will save someone else the agony of trying to write recursive routines against a flat DataTable.

    -Brendan

  • Too Cool - the Wayback Machine

    I'm always the last one to find out about stuff, but this is so cool, that I had to blog about it.

    Have you ever told someone, “I developed company X's website” when in fact, the site has been re-developed numerous times since you worked on it?  Sometimes this can work out in your favor. For example, I worked on Cannondale's site back in the day.  Today this is a cool site, so people say “wow that's impressive!” But other times it can work against you, like when the site is not on the web any more, or has changed for the worse.  For example, the first site I launched back in 1995 for Analysis & Technology, Inc. is  gone.  Enter the Wayback Machine.   It will let you time-travel so to speak, and let you view an old version of a site.  So, here's the version of Cannodale.com that I worked on.  Not so impressive, huh?  But here's Analysis & Technology's site circa 1995.  Not bad for 1995, if I do say so myself. Especially when you consider that www.sun.com looked like this.

    -B

  • Strongly-Type a DropDownList with Enumerated Types

    OBSOLETE CONTENT
    The author of this post has determined that this content is obsolete. Use at your own risk! Blog posts are a point-in-time snapshot of the blogger's thinking and should not be assumed to represent this blogger's current opinions. This post was left up for historical purposes.

    If you're like me, you abhor any non-strongly typed sections of code like nature does a vacuum.   Sometimes, it may seem unavoidable, like when creating a DropDownList  (or other list type in the System.Web.UI.WebControls namespace, such as CheckBoxList).  Here we usually resort to HTML definitions or other hard-coded representation of the ListItems that are to be presented.  Your code might look like this:

             <asp:DropDownList id="sizeList" runat="server">
              <asp:ListItem Value="0">Small</asp:ListItem>
              <asp:ListItem Value="1">Medium</asp:ListItem>
              <asp:ListItem Value="2">Large</asp:ListItem>
              <asp:ListItem Value="3">ExtraLarge</asp:ListItem>
             </asp:DropDownList>

    There's a problem with this approach, however.  If the  possible values in the list ever change, you'll be faced with changing your presentation code, and any code that depends on any specific constants representing the possible values.  You can get around these problems by strongly-typing  the possible values for an enum, and using this to both generate the list and work with the user's list selection.

    First, create a strongly-typed enum containing your possible values, we'll use t-shirt sizes for an example:

    public enum TShirtSize
    {
        Small  = 0,
        Medium = 1
    ,
        Large  = 2,
        ExtraLarge = 3
    }

    Now, to dynamically create a drop-down list, use the following code:

    DropDownList ddl = new DropDownList();
    foreach(TShirtSize siz in Enum.GetValues(typeof
    (TShirtSize)))
    {
       
    ddl.Items.Add(
          new ListItem(siz.ToString(), Convert.ToInt32(siz).ToString())
        );
    }

    Now, to get back your strongly-typed value, use the following after a postback to find out the user's selection.

    TShirtSize selectedSize = (TShirtSize) Convert.ToInt32(ddl.SelectedValue);

    Easy, and strongly typed!

    -Brendan

  • "Sun and Microsoft love fest"

    Very interesting stuff.  Especially James Avery's comments. 

More Posts

Our Sponsors