Home

Archived Posts from “Getting Started”

More on SubSonic and SSMS Tools Pack

11

December

I’ve publicly praised SubSonic and SSMS Tools Pack, but I haven’t posted adequate information on how one installs and uses the tools for their own development.  A colleague of mine was lucky enough to inherit my application recently and having this information documented would have come in really handy.  All the same, I gave a crash course on the two tools today. 

Here’s my quick rundown of SSMS Tools Pack and SubSonc.  Hopefully it is enough to get you (and my co-worker) started.

Reference and Installation Information

SSMS Tools Pack 1.1 was created by Mladen Prajdi?.  Here’s the feature list.  Note, I am using SQL Server Management Studio Express 2005 SP2 locally, however, SSMS Tools Pack support this as well as SQL Server Management Studio 2008 (Express).  Choose your poison here and install using the default settings.

SubSonic 2.1 was created by Rob Conery and the team includes an impressive list of coders.  Note, I am using version 2.0.3 which is the current stable release.  You can download version 2.1 although I’ve heard mixed reviews.  In either case, install using the default settings.

Using SSMS Tools Pack

I use SSMS Tool Pack to generate my CRUD stored procedures.  That’s right.  I still use stored procedures even when I access my database through a generated DAL. 

It is just a preference, but the first thing I suggest is to update the generated stored procedure naming convention by navigating to SSMS Tools > Create CRUD > Options.  Here, you update the stored procedure name prefix from “usp_” to “GSP_” on all five tabs.  “GSP” stands for Generated Stored Procedure, by the way.

Next, it’s time to define the database schema.  Be sure to include primary keys on all tables. 

Finally, generate the CRUD routines by right-clicking on the database in Object Explorer then selecting SSMS Tools > Create CRUD.  The resulting scripts will be generated to a new query window for review and execution.

Using SubSonic

I use the bare bones of what SubSonic has to offer.  I primarily use the tool to generate my DAL from which I only create, read, update and delete my data through stored procedures. I also use SubSonic to generate a set of templated classes which I include in my solution’s common class library. Believe it or not, I have written about SubSonic custom templates before.

Before going any further, I would suggest watching the “Getting Started” tutorial which can currently be found towards the bottom-right of the SubSonic Project Home Page. The tutorial covers basic SubSonic DAL concepts including configuration, a DAL class library, managing custom and generated code through use of partial classes and Visual Studio external tools.

Per the tutorial, you’re going to want to set up your Visual Studio external tool shortcuts.  This can be done by navigating to Tools > External Tools. In my case, I generate my DAL and Common library so I create two external tool references. I like including all database access and template information in the command arguments although SubCommander is smart enough to leverage the settings in your app.config file. 

Once the external tools are set up, you may now generate your DAL code by selecting the DAL project in the Solution Explorer followed by the execution of the associated external tool command. Code will be added to the configured (most likely “Generated”) folder and each file can be included/excluded from the solution as necessary.

Moment of Truth

Hold your breath.  Cross your fingers.  Hit F5.  Eat more sugar cookies.


Getting Started with CruiseControl.NET

29

January

I consider myself a neophyte when it comes to continuous integration (CI), but having read up on the topic, “played around” a bit, reviewed a couple of products, and having now incorporated it into our standard development practices, I am starting to hold my own.  If nothing else, the benefits of continuous integration are now obvious and, well, I can’t imagine ever turning back. 

For me, the power of continuous integration extends far beyond build validation.  CI it has become a welcome management tool which allows me to keep my finger on the pulse of numerous developed products as well as individual developer contributions.  Though I am very interested in the overall success/fail state of the current build, equally valuable is the the notifications which email specified team members the code change log which accompanies each build. (i.e. A list modified files and associated comments since the last automated build.)  If you are responsible for overall project success (which typically includes management of deliverable, code quality, task distribution, etc) then continuous integration is for you.

As I mentioned earlier, I reviewed a few products.  Last year, I reviewed FinalBuilder which provided me a nice and easy introduction into this space.  Based almost completely on its popularly and price tag (free), I have since turned to CruiseControl.NET.  I will not claim that was able to quickly get up and running with CruiseControl.NET.  At times, I was down-right questioning if I was smart enough to figure out the product and its configuration.  But, alas, it is now running on a dedicated build machine and my team and I are all the better for it. 

Please let it be known that I am not a wizard when it comes to CruiseControl.NET.  I am, however, good at is documentation of repeatable actions and I tried to capture the steps on getting started with CruiseControl.NET below.  As always, any feedback is greatly appreciated.

By the way, if you are looking for general information on continuous integration or CruiseControl.NET, you are not going to find here.  For more information, you may wish to consult the following:  What is Continuous Integration and What is CruiseControl.NET.

That’s basically it.  Best of luck!

 

1. Find a Build Machine

Though CruiseControl.NET could be installed on a development machine, I recommended that it be installed on a dedicated build server. Your build server should have access your source control repository and an optimal STMP server.  The server should have IIS and the NET Framework installed as well.  More information on the build server to follow…

 

2. Install CruiseControl.NET

Download CruiseControl.NET Server and Dashboard and install using provided default selections. 

http://downloads.sourceforge.net/ccnet/CruiseControl.NET-1.3-setup.exe?modtime=1182463056&big_mirror=0

 

3. Install MSBuild

If you are working with .NET 2.0+ applications, you can build using MSBuild. Otherwise, you may need to learn a bit about NANT.  All of the provided sample configurations below assume you will be using MSBuild. 

The MSBuild DLL is not included in initial CCNET Server installation, but it can be downloaded from the ThoughtWorks site: http://ccnetlive.thoughtworks.com/MSBuildXmlLogger%2DBuilds/. To install, simply copy the ThoughtWorks.CruiseControl.MSBuild.dll into C:\Program Files\CruiseControl.NET\server\ location.

 

4. Install Source Control Client

You will potentially need to install your source control client on the build machine. For the samples provides, we are using Borland StarTeam 2005.  CruiseControl.NET integrates with just about every source control system I could think of, so if you are using something other than StarTeam, you will want to consult the Source Control Block documentation.

 

5. CruiseControl.NET Server Configuration

CruiseControl.NET Server is driven by CCNET configuration file settings. After the fresh install, the configuration is essentially empty and requires manual updates to the ccnet.config file itself. As far as my knowledge, there is no associated configuration editor.  First things first, crack open “C:\Program Files\CruiseControl.NET\server\ccnet.config” in Visual Studios or your favorite XML editor. (There is shortcut under All Programs > CruiseControl.NET > CruiseControl.NET Config.)

If you have a pre-configured ccnet.config file available, simply overwrite the file content. If you are starting from scratch, you may wish reference the online CruiseControl.NET configuration overview and review samples: http://confluence.public.thoughtworks.org/display/CCNET/Configuring+the+Server.  Additional example configuration files were installed on your build box as well: C:\Program Files\CruiseControl.NET\Examples.  They are worth a look.

The bad news: Though you will find examples sprinkled throughout the ThoughtWorks site and the locations noted above, you will most likely need to muck around with your own config file for a while until you get it right.  Additional samples are provide below, but just as I wasn’t able to find the magic configuration combination to get my server running right off the bat, I bet you won’t either. 

The good news: Getting the right configuration was trail-and-error process for me.  I kept the configuration very simple at first and then built upon it.  Hopefully the next steps can help you with your troubleshooting.

 

6. Start CruiseControl.NET Server

The CCNET Server is not started at the time of installation. Thus, you will need to start the service manually: Administrative Tools > Services > CruiseControl.NET Server > Select > Start the service.

If the service fails at startup, it will immediately stop and present the following generic dialogue:

The CruiseControl.NET Server service on Local Computer started and then stopped. Some services stop automatically if they have no work to do, for example, the Performance Logs and Alert service.

If you encounter this error your first stop is to consult the logs: C:\Program Files\CruiseControl.NET\server\ccnet.log. By default, the file contains verbose logging which is helpful (although somewhat difficult to navigate.)  Believe me, the logs are your fried.

Based on the log file feedback, I suggest tweaking the ccnet.config file and then restarting the service – repeating until the service is fully configured.  And, if it is easier for you, you may run the CCNET Server via the command window: CD C:\Program Files\CruiseControl.NET\server > ccnet.exe.  This approach will render errors in the cmd window rather than having to monitor the ccnet.log file.  It was a time saver for me at least.

Once the project is successfully setup, you will see something similar to the following listed in the logs:

· [CCNet Server:DEBUG] The trace level is currently set to debug. This will cause CCNet to log at the most verbose level, which is useful for setting up or debugging the server. Once your server is running smoothly, we recommend changing this setting in C:\Program Files\CruiseControl.NET\server\ccnet.exe.config to a lower level.

· [CCNet Server:INFO] Reading configuration file “C:\Program Files\CruiseControl.NET\server\ccnet.config”

· [CCNet Server:INFO] Registered channel: tcp

· [CCNet Server:INFO] CruiseManager: Listening on url:tcp://localhost:21234/CruiseManager.rem

· [CCNet Server:INFO] Starting CruiseControl.NET Server

· [PROJECTNAME:INFO] Starting integrator for project: PROJECTNAME

At this point, the Server is waiting to initiate the next build. Based on the config file <triggers> setting it could take a while to get the checkout and build to fire. Adjust the following setting to around 10 seconds while still in the testing phase:

<triggers>
  <intervalTrigger name="continuous" seconds="10"
                   buildCondition="IfModificationExists"/>
</triggers>

On a similar note, the Server restarts itself automatically each time the ccnet.config file is modified.

 

7. Potential Gotchas

I ran into a couple specific cases while debugging which I suspect could be common issues. 

1. Ensure the MSBuild timeout value allows enough time to the build to complete. This will otherwise return in a failure which wasn’t easy to troubleshoot.

<msbuild>
  <timeout>600</timeout>
</msbuild>

2. For web solutions, update the TargetPath for the Debug and/or Release build of the application to be outside of the source application directory. Otherwise, you will receive the following error:

ASPNETCOMPILER : error ASPRUNTIME: The precompilation target directory cannot be in the same tree as the source application directory.

This can be done by modifying the following in the solution file:

Debug.AspNetCompiler.TargetPath = “c:\ccnet\PrecompiledWeb\SampleWeb\”
Release.AspNetCompiler.TargetPath = “c:\ccnet\PrecompiledWeb\SampleWeb\”

Alternative, one may update the Output location found in the application MSBuild properties.

You may be wondering why an updated solution won’t be updated with the next scheduled build.  As it works out (and makes sense) only changes which are applied to source control are pulled onto the build box. 

 

8. Automating Your Builds

Once the build process is running successfully, modify the <intervalTrigger> setting to a reasonable value and then update the “CruiseControl.NET Server” Service Startup Type to Automatic and then Start the service.  I might suggest also crossing your fingers for the next day or so.

 

9. Monitoring Your Builds

The CCNet Web Dashboard Application is used for reporting a wide range of information. At one end of the scale it reports summary details of all projects being managed by CruiseControl.NET and at the other it can give specific metric output for any specific build.  The Dashboard is setup with your initial installation.  You may access the Dashboard application by navigating a location similar to the following: http://buildbox.com/ccnet/ViewFarmReport.aspx.  For more information on the Web Dashboard: http://confluence.public.thoughtworks.org/display/CCNET/Web+Dashboard

The CCTray an optional utility for use with the CruiseControl.NET Continuous Integration server. It provides feedback upon build progress, and allows control over some of the server’s operations.  As “optional utility” implies, the CCTray isn’t included with the base installation.  You may download the Windows Tray Application from the following location and install using provided default selection: http://downloads.sourceforge.net/ccnet/CruiseControl.NET-CCTray-1.3-Setup.exe?modtime=1182463076&big_mirror=0. There isn’t much to using the CCTray but I do consider it a handy add-on.  Basically, you will find a shortcut to the CCTray on your desktop. Launch the application to begin monitoring the automated build(s) status and schedule.  The information provides via the CCTray is very similar to that which is provided in the Dashboard application.  For more information on CCTray: http://confluence.public.thoughtworks.org/display/CCNET/CCTray.

 

Sample Configuration Files

If you have made it this far, I really, really hope your required configuration is similar to mine.  If so, this is your golden ticket.  I have provided two flavors of configuration files below. You will undoubted need to tweak the files a bit (replace the project locations and names along with credentials will obviously be required), but hopefully these will help get you started.  By the way, the formatting of the XML leaves something to be desires as I have formatted to fit within the given real estate.

 

Windows Service, StarTeam, MSBuild, Emailing and Unit Tests

<cruisecontrol>
  <project name="SampleService" queue="Q1" queuePriority="0">
    <workingDirectory>c:\Projects\Services\SampleService
      </workingDirectory>
    <artifactDirectory>c:\ccnet\artifacts\Services\SampleService
      </artifactDirectory>
    <category>Continuous Builds</category>
    <webURL>http://buildbox.com/ccnet/server/local/project/
      SampleService/ViewProjectReport.aspx</webURL>
    <triggers>
      <intervalTrigger name="continuous" seconds="600"
                       buildCondition="IfModificationExists"/>
    </triggers>
    <state type="state" directory="c:\ccnet\state"/>
    <labeller type="defaultlabeller">
      <prefix>Build-1.0.</prefix>
      <incrementOnFailure>false</incrementOnFailure>
    </labeller>
    <sourcecontrol type="starteam">
      <executable>c:\Program Files\Borland\StarTeam 2005\
        stcmd.exe</executable>
      <project>Project</project>
      <username>user</username>
      <password>password</password>
      <host>10.1.10.100</host>
      <port>11111</port>
      <path>Projects/Services/SampleService</path>
      <autoGetSource>true</autoGetSource>
    </sourcecontrol>
    <tasks>
      <msbuild>
        <executable>C:\WINDOWS\Microsoft.NET\Framework\
          v2.0.50727\MSBuild.exe
        </executable>
        <workingDirectory>C:\Projects\Services\SampleService
          </workingDirectory>
        <projectFile>SampleService.sln</projectFile>
        <buildArgs>/noconsolelogger /p:Configuration=Debug /v:m
          </buildArgs>
        <targets>Clean;Build</targets>
        <timeout>600</timeout>
        <logger>ThoughtWorks.CruiseControl.MsBuild.XMLLogger,
          C:\Program Files\CruiseControl.NET\server\
          ThoughtWorks.CruiseControl.MsBuild.dll</logger>
      </msbuild>
      <msbuild>
        <executable>C:\WINDOWS\Microsoft.NET\Framework\
          v2.0.50727\MSBuild.exe</executable>
        <workingDirectory>C:\Projects\Services\SampleService
          </workingDirectory>
        <projectFile>UnitTestBuild.proj</projectFile>
        <buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag
          </buildArgs>
        <targets>Tests</targets>
        <timeout>1500</timeout>
        <logger>ThoughtWorks.CruiseControl.MsBuild.XMLLogger,
          C:\Program Files\CruiseControl.NET\server\
          ThoughtWorks.CruiseControl.MsBuild.dll</logger>
      </msbuild>
    </tasks>
    <publishers>
      <merge>
        <files>
          <file>c:\ccnet\artifacts\Services\SampleService\
            mbUnit-testResults.xml</file>
          <file>c:\ccnet\artifacts\Services\SampleService\
            msbuild-results.xml</file>
        </files>
      </merge>
      <xmllogger/>
      <email from="no-reply@buildbox.com"
              mailhost="localhost" includeDetails="TRUE">
        <users>
          <user name="User 1" group="BuildMaster"
                  address="user.one@buildbox.com"/>
          <user name="user 2" group="TechLead"
                  address="user.two@buildbox.com"/>
        </users>
        <groups>
          <group name="BuildMaster" notification="always"/>
          <group name="TechLead" notification="change"/>
        </groups>
      </email>
    </publishers>
  </project>
</cruisecontrol>

Web Application, StarTeam, MSBuild, Emailing, and Build Dependencies

<cruisecontrol>
  <project name="SampleWeb" queue="Q2"
           queuePriority="1">
    <workingDirectory>c:\Projects\Web\SampleWeb
      </workingDirectory>
    <artifactDirectory>c:\ccnet\artifacts\Web\SampleWeb
      </artifactDirectory>
    <category>Continuous Builds</category>
    <webURL>http://buildbox.com/ccnet/server/local/project/
      SampleWeb/ViewProjectReport.aspx</webURL>
    <modificationDelaySeconds>15</modificationDelaySeconds>
    <triggers>
      <intervalTrigger name="continuous" seconds="3600"
                       buildCondition="IfModificationExists"/>
      <projectTrigger project="SampleData">
        <!-- Force build when data component is successfully built. -->
        <triggerStatus>Success</triggerStatus>
        <innerTrigger type="intervalTrigger" seconds="30"
                      buildCondition="ForceBuild"/>
      </projectTrigger>
    </triggers>
    <state type="state" directory="c:\ccnet\state" />
    <labeller type="defaultlabeller">
      <prefix>SampleWeb-Build-</prefix>
      <incrementOnFailure>true</incrementOnFailure>
    </labeller>
    <sourcecontrol type="starteam">
      <executable>C:\Program Files\Borland\
        StarTeam Cross-Platform Client 2006 R2\stcmd.exe</executable>
      <project>Project</project>
      <username>user</username>
      <password>password</password>
      <host>10.1.10.100</host>
      <port>11111</port>
      <path>Projects/Web/SampleWeb</path>
      <autoGetSource>true</autoGetSource>
    </sourcecontrol>
    <tasks>
      <msbuild>
        <executable>C:\WINDOWS\Microsoft.NET\Framework\
          v2.0.50727\MSBuild.exe</executable>
        <workingDirectory>C:\Projects\Web\SampleWeb
          </workingDirectory>
        <projectFile>SampleWeb.sln</projectFile>
        <timeout>900</timeout>
        <buildArgs>/clp:PerformanceSummary /verbosity:d
          </buildArgs>
        <logger>C:\Program Files\CruiseControl.NET\server\
          ThoughtWorks.CruiseControl.MsBuild.dll</logger>
      </msbuild>
    </tasks>
    <publishers>
      <xmllogger />
      <buildpublisher>
        <publishDir>c:\ccnet\artifacts\Web\SampleWeb</publishDir>
        <useLabelSubDirectory>true</useLabelSubDirectory>
      </buildpublisher>
      <email from="no.reply@buildbox.com"
              mailhost="localhost" includeDetails="TRUE">
        <users>
          <user name="User 1" group="BuildMaster"
                  address="user.one@buildbox.com"/>
          <user name="user 2" group="TechLead"
                address="user.two@buildbox.com"/>
        </users>
        <groups>
          <group name="BuildMaster" notification="always"/>
          <group name="TechLead" notification="change"/>
        </groups>
      </email>
    </publishers>
    <externalLinks>
      <externalLink name="Sample Web"
             url="http://buildbox.com/SampleWeb/default.aspx" />
    </externalLinks>
  </project>
</cruisecontrol>


Getting Started with SubVersion

19

January

Over the past decade, I’ve primarily used two version control products: Visual Source Safe and Borland StarTeam.  I was “forced” into using StarTeam about 5 years ago, but having used it day-in and day-out for so long, I’ve come to recognize it as the superior of the two products (hands down.)  Through blogs and open source projects, SubVersion has gained my attention and I’m now giving it a whirl as well.  Having just installed it and TortoiseSVN (both open source) on my laptop, I thought I would walk you through my steps:

SubVersion

The goal of the Subversion project is to build a version control system that is a compelling replacement for CVS in the open source community. For a full list of features, visit the site: http://subversion.tigris.org/

For Windows Installations, you may find the latest installer (svn-1.4.2-setup.exe) here - http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91. A list of other packages are here.

Just follow the installer steps.  The installation is quick and painless…

TortoiseSVN

Tortoise is a  SubVersion client, implemented as a windows shell extension. As stated on their site:

TortoiseSVN is a really easy to use Revision control / version control / source control software for Windows. Since it’s not an integration for a specific IDE you can use it with whatever development tools you like.  TortoiseSVN is free to use. You don’t need to get a loan or pay a full years salary to use it.

The image below gives you an idea of what Tortoise has to offer.  To learn more, visit http://tortoisesvn.tigris.org/

 

 

 

 

The latest TortoiseSVN installer (TortoiseSVN-1.4.1.7992-win32-svn-1.4.2.msi ) can be found on the downloads page - http://tortoisesvn.net/downloads

This installation is easy as well, but it did require a reboot. 

Getting Started

I followed this Practical Guide to SubVersion on Windows with TortoiseSVN to get myself going.  You may also find Tortoise manuals here or they are available by pressing F1 in any TortoiseSVN dialog once the product is installed. 

I won’t say the setup is very intuitive and I was happy to find a tutorial.   Most importantly, I’m really happy I have friends who have been using SubVersion/Tortoise for a while now.  In fact, I’m hoping to provide a little more insight into using SubVersion once I get the skinny from Jon Galloway next week. 

Stay tuned…


Google Sitemap Setup

16

November

 With the attention that Microsoft, Yahoo! and Google are getting for agreeing on a standard sitemaps protocol, I figured it was probably time I got one in place which meets standard found on sitemaps.org

Though I’m sure I would have had a lot of fun using the Google Sitemap Generator Python scripts recommended by Google Webmaster Tools, I opted to go with yet another WordPress Plugin instead. 

Sitemap Generator for WordPress v2 was a single file download and a single click installation.  There’s a beta release of the next version available, but I stuck with version 2.

Though the plugin pings Google and let’s them know about the new sitemap.xml file, I still visited Google Webmaster Tools and set things up manually as well.


SubSonic - Another Look at Code Generation

05

November

Last month, I wrote Manual Code Generation, an article which shared, in my view, the pros and the cons of code generators.  In this same article, I took sides and expressed that “I am not a fan of code generation.”  My stance came as no surprise to some — particularly my buddy (read archenemy) Jon Galloway.  We’ve gone back and forth on this topic for a few years now so, of course, Jon replied to my post with arguments in favor of code generation.  Along with arguments, he also offered a few suggestions; the best of which was to check out SubSonic.  Actually, Jon simply asked, “Have you checked out  SubSonic?”  but I know this was just his polite way of asking me to please check it out before I continued to publicly embarrass myself by making bold statements about things which I have fairly little exposure simply because I effectively dismissed them years ago.  

I have now checked out SubSonic.  In an effort to get in the last word, here’s my review:

First Impressions

The SubSonic project is hosted on CodePlex.  If you are not familiar, CodePlex is Microsoft’s open source project hosting web site. You can use CodePlex to create new projects to share with the world, join others who have already started their own projects, or use the applications on the site and provide feedback. Through CodePlex your project team may manage news feeds, releases, discussions, issues, source code and licensing.  I know this is a review of SubSonic, but CodePlex is worth talking about (especially since it helped make a good first impression.)

Nearly Everything You Need To Know

The project’s main page has nearly everything one needs to get started:

Product Overview 

The overview provides a very quick description of the product’s core feature list.  To be honest, I wish more detailed information was provided here, but I think I got the gist.  At its essence, SubSonic includes:

  1. A Data Access Layer (DAL) Builder which generates CRUD-enabled objects (which, in turn, represent selected database tables) and complementary strongly-typed collections.
  2. A complete utility toolset complete with Rails-like scaffolding which effortlessly builds admin-like web pages, migrations or DB versioning and code generators.
  3. A dynamic query tool that lets one use SQL Server, mySQL and/or Enterprise Library without having to know the underlying SQL syntax.
  4. An object-relational (OR) mapper which extends to stored procedures and views.

My one recommendation would be to elaborate on the feature set and tell a little more about the product in the overview.  Answer questions like “Why was this effort undertaken?” and ”What problem does SubSonic solve?”  That sort of thing.  I will get into this a bit more in the Webcast section, but I think the “Welcome to the ActionPack for .NET!” content found on the sample website default page would be a nice addition to the project main page. 

Source Code Download 

SubSonic 1.0.5 was recently released on 10/24/2006.  It’s a 1.3 MB .zip file download which includes the complete SubSonic Actionpack, Sample Website and Dependencies.  A double-click on the unzipped solution file, a quick update to the Northwind connection string and I was up and running.  You can’t beat that.

Starter Site Download 

Latest version of the starter site project was released on 10/24/2006 as well.  It came packaged up as a .vsi (Visual Studio Content Installer) file which, unfortunately, failed when I attempted to run it  [1].  As I mentioned previously, the Sample Website source code was provided which I’m guessing is what would come along with the Starter Site so I was still in business.

Webcast 

This demo was a treat.  I am so pleased I spent the time to watch it.  Not only did the webcast walk through highlighted functionality, but, in my opinion, it gave the product a “story.”  You see, when I am at a gallery or museum, I tend to spend more time reading about the art/artist then actually admiring the work itself.  I have a hard time appreciating a painting until I understand its background.  I really like to know what the piece represents and what drove the artist to create it.  That’s what the 20-minute webcast gave me.  It gave SubSonic a personality.  It also more deeply shared the philosophy behind the product which is Rails.  Though the written overview touched upon elements of Rails (scaffolding), the demo touched upon one of its guiding principles (Convention Over Configuration) and base architecture (MVC, model-view-controller) in the words of the author.  If you are interested in trying out the SubSonic ActionPack you should absolutely watch the webcast.

Playtime

Now that SubSonic was running on my machine, it was time to start playing around.  I started with the basics which was basically everything which was discussed in the demo. 

BuildProvider Class

If it hasn’t been mentioned already, SubSonic takes advantage of  a new feature in .NET 2.0, the System.Web.Compilation.BuildProvider Class, to generate the DAL at compile time.  There’s good reason why I’m placing a lot of  emphasis on the use of the BuildProvider: First, you are generating and working your code within the same tool – Visual Studio. Also, your code is generated automatically when you build your application.  This means your application code and generated code will never be out of synch again. Finally, I wasn’t previously familiar with the BuildProvider class, thus it made SubSonic a great learning tool.

I should mention that the generator is wired up really nicely and you don’t actually need to know a thing about the BuildProvider.  All you need to know is classes/collections will be generated for tables listed in the App_Code/builder.abp file.  You can even keep the default (not touch a line of code) and generate classes for all tables.

Additional Documentation

I built the project and clicked through the Sample Website.  Again, I really like the content on the default page so be sure to spend some time here.  I then breezed through the short tutorials found in the “Setup” and “CRUD” sections since the WebCast had already provided me with the basics.

Data Access Layer

My main interest was working with the generated DAL.  Therefore, I spent the majority of my time in the “Query the DB” section.  I did encounter an issue with the “Use a Collection” example, but otherwise the samples provided for a great testing grounds [2].

At first glance, I personally thought the provided examples were dumbed down a little too much.  Sure, they were enough to get one started, but they didn’t go beyond the bare essentials. 

For example, what if one wishes to filter their result set by more than one criterion.  How is this done?  After fiddling around a bit, I discovered this is as easy as making more than one call to the Query object’s AddWhere() function, but I wouldn’t have known without some experimentation.

Actually this is a nice segue. 

Knowing SubSonic

I’ve commented in the past that generated code is difficult to write and maintain unless you have a firm, working knowledge of the code generation tool itself.  What I mean by this is the generated code (in this case the exposed functions and methods available in the SubSonic DAL) uses custom syntax which one can only learn through using the tool and generated objects. 

The Query object’s AddWhere() function acts a good example.  Though it’s easy to query on multi-parameters, you have to learn SubSonic’s language before knowing how to do so.  This makes for an interesting point.  The documentation states that SubSonic “lets you use SQL Server and the Enterprise Library without having to know SQL.”  Though this is true, instead of learning SQL, you need to learn SubSonic’s language.  

Sticking to Conventions

To the creator’s credit, it appears that time was dedicated to making the tool and, in turn, the DAL consistent and intuitive.  SubSonic is a working example of  “Convention Over Configuration”  which makes learning how to use the product a lot easier.  There are numerous examples of this throughout the code, but most glaring is the decision to use singular, rather than plural, forms of object names.  Even if the underlying database table is named Products (plural), SubSonic is configured to generate a ProductCollection rather than a ProductsCollection.  Once you start understanding SubSonic’s conventions and patterns, you can start to navigate around the codebase with more confidence. 

(Of course, I had to look at the PluralToSingular utility function.  It will work in most cases, but the ever-present Octopi table is going to cause problems.)

Writing SubSonic

One big code generation con, in my opinion, is that someone has to spend time writing the code.  Though my point holds water, Jon argued that someone has already written SubSonic so this shouldn’t be a problem for me.  Well, maybe I’m too picky, but I’ve found that most software doesn’t do everything that I want or need and I wind up at least tweaking the generated classes/collections. 

For example, I like to be able to access collection items by key as well as by index.  The CodeSmith implementation, which I mentioned in my earlier write-up, didn’t provide this functionality.  Additionally, functions like Exists() weren’t available either.   If I recall, these custom collections were inheriting from System.Collections.CollectionBase which isn’t fall that full-featured.  SubSonic’s generated collections are a bit more robust (they inherit from System.Collections.Generic.List ) but I still can’t access, add or remove an item from the collection by key.  In the end, even though someone has already written the code, I will also need to spend time writing code if I would like this functionality. 

Code Regeneration

With this said, I wouldn’t necessarily have to modify the code generator itself.  Since SubSonic takes advantage of partial classes, I could easily maintain app-specific collection code with no concern that it would be over-written with the code generated by the next compile.  Along these lines, as Jon pointed out, SubSonic does support handcrafted code very well.  Subsonic also supports database changes as the DAL is safely regenerated when the project built.

DAL Focused

If you use the provided scaffolding model you will find it can quickly generate admin pages based on a database table and the associated DAL objects.  In the example project, scaffolding is in place to administer the Products table. What one gets out-of-the-box with this example is a list of all products along with a link add or edit. On the edit page, one may modify any of the field values (with the exception of an identity column.  Item deletion is done on the edit page as well.

Though scaffolding is in place to quickly generate admin pages, the presentation layer is not the ActionPack’s focus.  SubSonic’s bread and butter truly is the DAL which I consider a very wise approach to code generation.  In fact, in the demo, it even suggests that CRUD scaffolding should be considered for developer use only as it is presumably non-performant. I have to give SubSonic’s team a lot of credit for making scaffolding available yet sharing the limitations openly and not pushing this feature down the throats of end users.  I also really respect the decision to focus heavily in one area (the DAL), making it really solid, and not get distracted by other not-as-important features.

Keep It Simple, Stupid 

SubSonic’s DAL architecture follows the KISS principle which I admire.  For example, though the Northwind EmployeeTerritories table establishes an obvious relationship between Employees and Territories through foreign key constraints, the DAL doesn’t.  One might assume the Employee object would own an internal Territories Collection, but it doesn’t.  SubSonic generates separate objects for each database table and they are managed completely separate in the DAL.  Period. 

I may be wrong, but I believe this means one would have to do the following in order to display the names of all Territories for Employee with the last name Griswold.

  1. Fill an EmployeeCollection where last name = Griswold
  2. Fill a EmployeeTerritoryCollection reference for each Employee.EmployeeID in the EmployeeCollection.
  3. Fill a TerritoryCollection for each EmployeeTerritory.TerritoryID in the EmployeeTerritoryCollection.

You may be thinking, “That’s not exactly simple.”  Well, you are right and you’re wrong.  The object model is simple and for 90% of what needs to be coded in a given application this is more than adequate.  Again, SubSonic keeps it simple and it’s objects are generated to meet the most-likely conditions — not the exception. 

That being said, one might consider using SubSonic’s Query Object to build the necessary SQL to populate the TerritoryCollection right off the bat, I’m not sure this is possible since the query would require joining at least two tables. 

On the surface this appears that we’re ina quite the predicament about 10% of the time, but SubSonic has an answer.   Which bring us to potentially my favorite feature… 

Using Stored Procedures

In the cases where you aren’t able to use Query Object and you aren’t able to leverage the Fill methods exposed in the collections, you can fall back to using stored procedures.  This will help you do whatever is needed.

I thoroughly appreciate SubSonic’s stance on the use of stored procedures. Basically, if you want to use them, the DAL provides ample support. (Each stored procedure in the database is wrapped in their own custom, publicly available function.) If you don’t want to use SPs, that’s fine too.   Make no mistake about it, however.  This product’s concentration is on building dynamic queries which is smart for a performance and usability stand point.

I’ve used code generation tools which attempt to generate a stored procedure for every CRUD condition which could be dreamed up.  I found that most of the routines performed just fine.  After all, it is difficult to slow down a query which pulls back a single row filtered on a clustered index.  However, other stored procedures tried to do too much.  For example, the routine which accommodated for filtering results on one or many fields through the use of “like” and “coalesce()” abused the SQL Server.  It is this type of performance nightmare which SubSonic cleverly avoids by, first and foremost, generating SQL and but also by making existing SPs available. 

One comment about the generated SQL:  Dynamic SQL has raised a lot of red flags because of SQL injection concerns, but SubSonic is actually leveraging parameterized queries which are a safe “dynamic” SQL implementation.  For example, ”select productname from products where productid = @productid;” is generated.  Prior to execution, the @productid parameter value is provided to the Command object.  This technique is as safe from SQL injection as a properly coded stored procedure simply because there is no room for injection.  Try to maliciously hack code into the @productid parameter and the command will fail entirely.

I had a chance to take a look at the algorithm to build SQL strings.  It is far less code than I expected and, as a matter of fact, it is here where I stumbled across a couple lines of code which made this entire review worth while.  Per the comment, the author really liked it too.  

   1:  //the following line is my favorite... Moe, Larry, Curly...
   2:  foreach (Where wWhere in qry.wheres) {
   3:      ...
   4:  }
    

Wrap Up 

After spending a few hours with the SubSonic, I don’t think its name does it justice.  I’m not saying the tool deserves to be called SuperSonic just yet, but Sonic seems perfectly reasonable.  If one were to draw a line in the sand, you still won’t find me on the side with the code generator advocates.  Maybe I’m straddling the line?  After all, I’d have to be a fool not to at least keep my eye on a tool which could potentially decrease my coding (and troubleshooting) time.  For now, let’s say that SubSonic has definitely gotten my attention.

Footnotes 

1: Installation of StarterKit Failed: Installation stopped because the directory for the ProjectType value did not exist. The project type is invalid for your installation of Visual Studio.

2: Query the DB > Use a Collection Error: Disallowed implicit conversion from data type varchar to data type money, table ‘Northwind.dbo.Products’, column ‘UnitPrice’. Use the CONVERT function to run this query.


Why Did I Start Using FeedBurner?

02

November

First, what is FeedBurner?  At it’s core, FeedBurner republishes blog feeds.  This alone isn’t all that exciting, however, the service provides so much more.

FeedBurner’s most attractive feature is it’s analytics.  The service keeps track of feed subscribers, applications used to access your feed, where your readers are located and a few other statistics. 

Not only does FeedBurner manage your analytics, it also helps build your user base by introducing easy ways for readers to subscribe to your feed (via RSS, HTML and/or email) and by submitting your posts to numerous search engines for easy indexing.  And, of course, there’s the attractive FeedBurner counter you see on everyone’s site these days.  I mean, who can resist clicking on that little baby?

FeedBurner presumably maintains your reader base as well.  This is done by ensuring your feed is compatible with all aggregators and by adding features to your post such as email options and links to social bookmarking services.  Additionally, FeedBurner lets you change your feed location.  If you happen to move your blog to another domain you are going to want to bring your readers with you, right?

Any of these features are good reason to sign up with the service, but why did I start using FeedBurner?  Mostly because everyone else is doing it.  That’s right.  I guess I submitted to the peer pressure. :)

If you are interested in setting up a FeedBurner account or if you want to know how to integrate FeedBurner into your site, keep reading.  I also go a little deeper into feature list mention above as well.

FeedBurner Account Setup

This part is easy and free. 

  1. Figure out your blog’s feed URL.  (I don’t know what it looks like for all blog types, but for WordPress it is similar to http://www.sitename.com/feed.)
  2. Visit FeedBurner and submit your feed URL.   
  3. Provide very little account information (blog name, user name, password, etc)
  4. Activate features.  I would suggest browsing through the options on the Optimize tab first.  I added some “FeedFlare” such as links on the footer of each post to comment counts, add to del.icio.us, add to digg and email.  I also modified my feed’s Title/Description.  Many of the “Optimize” features are free so go nuts.
  5. Head over the “Publicize” tab.  You will probably want to select all of the options under “PingShot.” This automatically notifies services like Technorati and Ping-o-matic when you publish a post.  If you would like to display the FeedBurner counter (chicklet) on your site, check out “FeedCount.” I would also recommend looking into ”Email Subscriptions” even though I haven’t activated this feature myself yet.  
  6. Wait about 24 hours and then have a look at the “Analyze” section.  Twenty four hours is the amount of time FeedBurner needs to start “building” your feed statistics.  If you need some instant gratification, “Live Hits” should be immediately available.
  7. Have a look at the premium service.  They aren’t expensive and they may be worth it to you.

Site Integration

How do you integrate a new FeedBurner feed into your blog?  After all, you may have millions of readers already tied to your current feed URL. 

If you are running WordPress, you are in luck. Check out the FeedBurner Plugin v2.1 from OrderedList.com.  The plugin detects all of the ways one might be accessing your WP feed.  For example, both http://www.johnnycoder.com/blog/feed/ and http://www.johnnycoder.com/blog/wp-rss2.php are valid feed URLs for this site.  After detection, the plugin will automatically start redirecting callers your new FeedBurner feed.  The redirection will allow you to track all subscriber - existing and new.  The plugin handles forwarding for your main post feed and optionally your main comments feed.  It is quick and easy to install and, to some extent, it will even walk you through the FeedBurner account setup. I was personally up and running in minutes and I understand the plugin works for both WP 1.5 and 2.0.

If you aren’t using WordPress and you can’t leverage this plugin, you’re going to have to find all instances of the RSS feed in your blog template and modify them to point to your new FeedBurner URL.  It should not be too hard, but it may be cumbersome.  You will also want to inform your readers of the feed URL change since they will have to resubscribe to your RSS.

Alternatively, if you have the means, write your own redirection routine at each entry point.  This way, you too, can automatically keep your current reader base.


Blogging for Beginners

01

September

My son was born 41 days ago and I felt it was my parental duty to show him off to the world (or at least to family and friends.) Since I spend most of my day online, I figured a blog would be super convenient (and non-intrusive) way for me to share photos of my son. Thus far, it is working out great and some have asked, “How did you do it?” Since I’m a coder, I think everyone figures I put the site together from scratch. I really appreciate the compliment, but nothing could be further from the truth. As a developer, it’s imperative that I consider all possible solutions and choose the best possible option. With a new baby, time and money (always key factors in determining the best solution) are scarce so I leveraged existing code and turnkey applications.

Registration: In another 5 years, it is going to be impossible to obtain [yourname].com so it was somewhat of a big deal to me to get my hands on [myson].com. A quick visit to godaddy.com and ~$30 later, I had the domain privately registered. Though the private registration is about $8 more than standard registration, I think it’s worth it. Ultimately, it means your personal information isn’t exposed to anyone at any time and it effectively eliminates all spam associated with the registration.

Cost: $30

Hosting: Since cost was the biggest factor in finding my host, I couldn’t be too particular when it came to options. Since I work for a MS shop, I would have really liked a host which supported .NET and SQL Server, but I knew I wasn’t going to find this on the cheap. And since I wasn’t going to find a host which supported my programming language of choice, I needed to find (rather than code) a blog. This is where BlueHost.com came in. They will host up to 6 domains for $6.95 / month. They support Perl, PHP and MySQL and they provide automatic installs of many, many products including 5 different PHP blogs.

Cost: $166 for two-year agreement

Blog: After about 30 minutes of research, I decided WordPress would support my blogging needs. Really, I only had a few requirements:

  1. Text and Image Support
  2. Site Templating Options
  3. Offline Blog Editors Support.

Since BlueHost.com provided a free installation of the product, it was a no-brainer.

Cost: $0

Blog Editor: I wanted the ability to write and publish my blog entries using a third-party tool. Though WordPress provides online admin tools, I’ve never met an online text/html editor which I’ve liked. Thus, I chose to go with WB Editor - a desktop blogging tool. Since using the product, I’m not particularly impressed. It is super-easy to use, but I’m a geek. I don’t want easy with barebones functionality. I’d prefer complex with lots of options.

Cost: $20 (You get what you pay for)

I recently thought there may be a business opportunity here. Setting up one’s own blog isn’t difficult (heck, check out Blogger on Google.com if you want easy), but the process isn’t necessarily easy for everyone. I don’t know if personal blog setup is something that the GeekSquad does already, but blogging is becoming more and more popular so maybe someone should capitalize on it.


ABOUT

CONTACT

RSS  

ARCHIVES

READ BY TOPIC


LINKS

LINK ADS