Ugh. We just learned a nasty truth about SQL Server's transaction handling, so here's some Google-juice for others with a similar problem. In our code, we were using SqlTransaction objects to maintain a transaction while updating the database.
This article, by Scott Mitchell, looks at SQL Server 2005's new TRY...CATCH syntax and how it simplifies rolling back transactions in the face of an error.