Monday, January 08, 2007

Last Friday, I got a chance to meet with the new customer.  I got up early, dusted off my hard hat and put on my best business casual clothes and took a 4-hour road trip to "Dinoland" (Texas' Permian Basin, land of dinosaur fossils and black gold).  We had our kickoff meeting at the local BBQ place, and then drove over to the gas processing plant, where I was able to sink my nicest shoes into 2 inches of mud.  I should have worn jeans and work boots like I had originally planned.  Anyway, we had a rather long engineering planning meeting.  At the meeting, the engineers drew all sorts of cryptic diagrams and spoke a language with which I am unfamiliar, though it did use English to connect the jargon.  And I thought to myself, so this is how we programmers must look like to outsiders - cryptic indecipherable language, UML and ORD diagrams that have the appearance of being "right", and inside jokes that they don't get but seem to crack everyone else up.  It was educational to be on the "outside" for a change.

posted on Monday, January 08, 2007 12:20:35 PM (Central Standard Time, UTC-06:00) by Christopher S. Velazquez

The tool that no .NET programmer should suffer without has gotten better!  New features are enumerated here.

posted on Monday, January 08, 2007 9:43:30 AM (Central Standard Time, UTC-06:00) by Christopher S. Velazquez
 Thursday, January 04, 2007

NAnt is great.  I have a script that compiles all my source files, builds the standalone installation packages, fires off Virtual PC for testing, and it can even FTP the installation package to my client's site.  It seems like there's nothing NAnt can't do.  But I needed to peel off the version number from the executable, and I couldn't find any easy way to do this in NAnt.  Fortunately, I discovered that it's really not that hard to create a custom task in NAnt in C#, then use it from the target.

Basically, you have to create a <script> block (as shown below) and create a class that inherits from Task.  The TaskName attribute is what you will use in the main NAnt script to call it.  Any property with a TaskAttribute attribute can be used as an XML attribute in the script, and you can set Required=true to require it.  The Task object has the Project property, which can be used to access anything at all to do with the build process.  I use it here to set a NAnt property and log to StdOut.  NAnt will compile the C# code on the fly (if you did everything correctly) and voila, anything you can think of is now possible.

Here is a sample from the build script I created. 

<project name="SomeNAntProject" default="DefaultTarget">

    <property name="version.number" value="0.0.0.0" />

    <target name="DefaultTarget">
        <getversioninfo filename="C:\Folder\MyExecutable.exe" />
        <echo message="${version.number}" />
    </target>

    <script language="C#">
        <code>
        <![CDATA[
        [TaskName("getversioninfo")]
        public class GetVersionInfoTask: Task {
            
        private string _fileName;

           [TaskAttribute("filename", Required=true)]
            public string FileName {
                get {return _fileName; }
                set {_fileName = value; }
            }
            
            protected override void ExecuteTask() {
            
                System.Diagnostics.FileVersionInfo fvi = 
                    System.Diagnostics.FileVersionInfo.GetVersionInfo(_fileName);
                    
                Project.Properties["version.number"] = fvi.ProductVersion;
                
                Project.Log(Level.Info, 
                    "   [script] Got version info for " + _fileName);
            }
        }
        ]]>
        </code>
    </script>
    
</project>
posted on Thursday, January 04, 2007 7:58:31 PM (Central Standard Time, UTC-06:00) by Christopher S. Velazquez
 Wednesday, January 03, 2007

My absolute favorite feature in MSIE 7.0 is the custom search providers.  If you can search via the URL's query string, you can use it.  One of my most used custom searches is BugMeNot, the compulsory registration bypass web site.  It's easy to set up BugMeNot so you can access it as easily as Google:

Go to the search dropdown and select "Find More Providers"

On the web page that comes up, type http://www.bugmenot.com/view/TEST as the URL and BugMeNot for the name.

Click install.  Now you can search BugMeNot straight from IE7.

posted on Wednesday, January 03, 2007 1:45:03 PM (Central Standard Time, UTC-06:00) by Christopher S. Velazquez

I found an interesting alternative data access layer (DAL) to NHibernate called SubSonic.  It was formerly called "ActionPack", but I guess there must be enough confusion with Microsoft's "Action Pack" that they changed the name.  SubSonic is open-source (MPL)

SubSonic has been hailed as "Ruby on Rails" for .NET developers.  There is a screencast of it here, prepare to be amazed.  It works kind of like this:

1) Add a reference to the SubSonic DLL
2) Modify your web.config with connection string info and SubSonic build provider info
3) Build the project
4) ...
Copyright (C) Sidney Harris.

5) Amazing!  Domain objects and data access layer have been automagically created!

I foresee this as a great way to quickly get a data-driven site up with a minimum of development effort.  Realizing this is not the end-all and be-all of data access, you are still free to use "traditional" ADO.NET techniques.  A recent benefit is that CodePlex has come out with an XmlProvider, so that if you would rather persist to XML instead of a database, it can handle that data access layer, too.  This thing keeps getting better and better.

posted on Wednesday, January 03, 2007 10:27:55 AM (Central Standard Time, UTC-06:00) by Christopher S. Velazquez
 Tuesday, January 02, 2007

I just recently started using Microsoft SQL Server Management Studio Express (SSMSE).  This free tool is intended for SQL Server 2005 databases, but it works just fine with MSDE and SQL 2000 databases, as far as I can tell.  SSMSE obsoletes the tools I have been using up to this point, namely Enterprise Manager and Query Analyzer.

Enterprise Manager is slow to open on most systems I've used.  I have a server instance with 20 databases and I can take a nap before the thing finishes opening up.  SSMSE uses demand loading of the tree nodes, so performance is a lot better.

The whole integration between Enterprise Manager and Query Analyzer has a more natural feel.  Nice job, MS!

posted on Tuesday, January 02, 2007 4:25:55 PM (Central Standard Time, UTC-06:00) by Christopher S. Velazquez

OK, I'm definitely not the first person in the world to figure this out, but it bit me in the behind last week.  So I figured I would share this bit of wisdom with you so it doesn't happen to you.

Most of the data that's stored in this MSDE (SQL Server) database lives in an "engineering variable data" table.  In this parallel universe, the term "variable" doesn't mean quite what we programmers think it should mean, so I'll call it a "datum"  A "datum" can have a value, a specification (that determines how it is used in a calculation), upper and lower limits, residuals, bound type, and other properties of interest to engineers.

I experienced a dreadful performance problem in the production system.  Out of necessity, the program would sometimes have to delete 10,000 records from the VariableData table and insert a new copy of those records.  In the development system with a much smaller database, this worked as intended.  However, when we started getting upwards of a million records in the table, this data replacement step would bring the program to its knees for 30-120 seconds.  Sometimes the queries would time out, gobble up RAM like candy on Halloween, or both.  I tried various hacks and workarounds to improve performance, including using a bulk insert, but to no avail.

We finally took a look at the indexes:

IX_SolutionCaseID: key to an integer in SolutionCase table
IX_Specification: key to a varchar(7), whose value can be one of 7 possibilities
IX_Guid: unique key for a uniqueidentifier
IX_VariableID: key to an integer in Variable table
IX_VariableVariableID: a redundant key

I realized that the way I get data out of the database is by SolutionCaseID and VariableID, which uniquely identifies a datum.  So the queries I was currently running were using one of the existing indexes and then doing a table scan to find the record I actually wanted. Ick.  So I added a new two-field key:

IX_SolutionCaseIDVariableID: added key for both SolutionCaseID and VariableID

Adding this index to a populated table only took a few seconds and it cut the wait time in half!

Next I started hacking away indexes that I never use.

IX_VariableVariableID: deleted - this had no noticeable effect on performance.
IX_Specification : deleted - this improved performance.  This is analogous to have an index on sex "M" or "F", which is always a bad idea.
IX_Guid: deleted - I never look up data by Guid, this is for UI magic only.  This had a huge benefit on performance

So the conclusions can be:

  • Avoid indexes on GUID columns, unless they are primary keys and that's how you look things up
  • If you look up on two fields a lot, make sure you have an index that contains both fields
  • Don't index on columns that have lots of repetitive data.  You might actually win with a table scan on this one!

And if you didn't know this already, you can always force an index to be used in a select query (use at your own discretion):

SELECT Field1, Field2, Field3 FROM TableName WITH (INDEX = MyIndexName) WHERE Field4 = 42

And now my client is much happier, and there was much rejoicing!

posted on Tuesday, January 02, 2007 2:19:36 PM (Central Standard Time, UTC-06:00) by Christopher S. Velazquez
 Monday, January 01, 2007

Last week, I came across XML Marker, a free XML editor that is great for simple tasks.  It doesn't have the full range of abilities of a commercial product like Altova XMLSpy or StylusStudio.  I have been using the evaluation versions of these commercial products to do simple XML editing, but I can't justify coughing up $500 for a simple XML Editor.  XML Marker bridges the gap: it doesn't suck like Microsoft's XML Notepad but it give you multiple views of your XML document like the big boys.  I edited the config file for this web site, and it works great.  It doesn't have schema validation built-in, and that would be a nice addition.

posted on Monday, January 01, 2007 12:49:36 PM (Central Standard Time, UTC-06:00) by Christopher S. Velazquez