Writing Gadgets with The Pimp

All I have to say is, damn Justice's head is freaking huge!  I can only see about 1/3 of the screen around it.  I can't imagine what the line of sight would be like if he still had that damned perm.

Oh, Gadgets are cool!  Not easy to dev (no docs) partially due to the beta state of the system still.  Although they are HTML and JavaScript, development of desktop gadgets requires support only for the IE standards of each.

If Justice's ears were any wider I'd swear he were a flying elephant.

At least he's now bent over sniveling about the fact everyone has been ragging on Macs.  I can see again!  Nothing is better than having Justice's misery bring me joy.

MSMQ at Edmonton Code Camp

I just wrapped up my presentation on MSMQ at Edmonton Code Camp.  I actually thought that I was going to finish pretty early, but in the end I filled most of the time slot.  The group wasn't huge, but it was quite interactive and asked some very good questions.

I had hoped to show a full walk through of MSMQ Trigger Services, but alas I couldn't get my COM components to register properly.  I'm going to spend some time getting this to work and then I'll post it up here.

I'm hoping to get some time in the future where I can run through a series of posts on MSMQ and MSMQ Trigger Services.

I did forget to mention my important links during the presentation, so here they are:

Published at

Edmonton Code Camp registration is closed

Steven Rockarts just told me that registration has closed for Edmonton Code Camp.  We have 102 people officially registered (plus one wait-listed...sometimes it pays to just ask people!) for tomorrows event.  This promises to be a stellar event for the developer community here in Edmonton.

When you show up in the morning find the registration table and sign in so you get your registration kit.  The kits are going to be awesome.  Also, stick around after the last presentations as we will gather in one of the rooms and do the prize draws.  If you aren't there to take the prize we will just redraw.

See you all tomorrow.

JP Boodhoo at Edmug

Tonight we (Edmug) hosted JP Boodhoo at our monthly gathering.  JP was, well, JP.  Great content.  Great knowledge transfer.  Great all around.  He talked about having an 'Ah-ha!' moment with TDD.  Tonight I had my own 'Ah-ha!' moment.  I actually saw JP take a drink from his water bottle!  Yes folks, it is more than just a fashion statement.

The side note to the meeting was the complete lack of preparation and pre-meeting verification by yours truly.  We arrived at our location (the always reliable and very capable Milner Public Library) only to find that the room we thought was booked, actually wasn't.  Needless to say panic set in for me as I scrambled, with the help of Steve 'The Harbin Hammer' Yang to try to rectify the situation.  After a number of calls to the booking agent (who was being bothered at home while she was sick) it was clear that there was no way we were getting into the room.  Luckily for us the wonderful Christina Gray (no relation to Justice, thank god for her) was able to help us find a location at DevStudio's lunch room.  To both Christina and DevStudios we owe a debt of gratitude.  No me on the other hand, I deserve an arse kicking for letting this happen.  It won't again. 

Oh, I checked, and we have confirmed bookings for the rooms on Saturday.  No need to worry about Code Camp having the same issues.

Published at

'Tis the season for change

I'm sitting here in my pod looking out the window at the river valley here in Edmonton.  The trees are changing colour and the sight is beautiful.  Along with those trees, I'm changing jobs too.  I figured it was time for me to go out and try the independent consultant thing.  I went out and found a contract to get me started and I've taken the leap. 

Tomorrow is my last day here and, in some ways, I'm a little sad to see it go.  This is the team/project that I cut my teeth on web apps, C#, CruiseControl, NUnit, NAnt, NCover and many other tools.  My PMs gave me a lot of leeway when it came to trying new things.  I will never forget one PM who I went to and asked if I could set aside developer time to write tests for existing code.  Not only did he immediately say yes, but he also formulated a plan for selling the idea to all the project sponsors.  I know it isn't the norm to have PMs who perfectly abstract away the issues affecting the project.  I know it isn't often that you get PMs who are open to your technical ideas.  Those are probably the two most difficult things for me to walk away from.

So with the end nearing at this job, and the world if you read the sign the bum down the street holds, I'm very excited about this new venture.  If you know of anybody who's looking for a contract coder, drop me a line.

Busy, but great, week for Edmonton geeks

This week is going to be out-freakin'-standing for geeks in Edmonton. 

On Thursday the 28th Edmug is holding its monthly meeting and we have brought back Jean-Paul Boodhoo for your 500 level presentation pleasure!  It looks like Model View Presenter – A Better Way To Factor Your Presentation Layer snuck out a win at the last minute in our polling for JP's topic.  Thanks to everyone for voting on the Edmug site.  Because of the close nature of this vote, I think we will try to get JP back to speak again in the future.

The other mind blowing event this week is Edmonton Code Camp which is being held on Saturday the 30th.  Last I heard there were still some seats available so register here to participate in the biggest developer event Edmonton will see in 2006.  The topics will include Ruby, OO Programming for Procedural Programmers, LINQ, System Transactions, Tools of the Trade, MSMQ, and much more.  Even better is that we have a stunning line up of speakers presenting on these topics.

If you have the time, come out and take in the great events happening this week.

Published at

Shit samples == shit coders

I read The Daily WTF.  I read Jeff Atwood's Coding Horror.  Tonight I read IBM's sample document for How to use a DB2DataAdapter with the DB2 .NET Data Provider.  All three are essentially the same thing.  Repositories for coding cluster-fucks.  The difference between IBM and the other two is that the code examples at the IBM site are presented as samples of how to write code.

I found this sample for C# code while I was poking around.  I never expect sample code to be extremely tight, but there is this one class that I have to show you.

  // Helper method: This method establishes a connection to a database
  public static DB2Connection ConnectDb(String[] argv)
  {
    String server = "";
    String alias = "";
    String userId = "";
    String password = "";
    Int32 portNumber = -1;
    String connectString;

    if( argv.Length > 5 ||
        ( argv.Length == 1 &&
          ( String.Compare(argv[0],"?") == 0           ||
            String.Compare(argv[0],"-?") == 0          ||
            String.Compare(argv[0],"/?") == 0          ||
            String.Compare(argv[0],"-h",true) == 0     ||
            String.Compare(argv[0],"/h",true) == 0     ||
            String.Compare(argv[0],"-help",true) == 0  ||
            String.Compare(argv[0],"/help",true) == 0 ) ) )
    {
      throw new Exception(
        "Usage: prog_name [dbAlias] [userId passwd] \n" +
        "       prog_name [dbAlias] server portNum userId passwd");
    }

    switch (argv.Length)
    {
      case 0:  // Use all defaults
        alias = "sample";
        userId = "";
        password = "";
        break;
      case 1:  // dbAlias specified
        alias = argv[0];
        userId = "";
        password = "";
        break;
      case 2:  // userId & passwd specified
        alias = "sample";
        userId = argv[0];
        password = argv[1];
        break;
      case 3:  // dbAlias, userId & passwd specified
        alias = argv[0];
        userId = argv[1];
        password = argv[2];
        break;
      case 4:  // use default dbAlias
        alias = "sample";
        server = argv[0];
        portNumber = Convert.ToInt32(argv[1]);
        userId = argv[2];
        password = argv[3];
        break;
      case 5:  // everything specified
        alias = argv[0];
        server = argv[1];
        portNumber = Convert.ToInt32(argv[2]);
        userId = argv[3];
        password = argv[4];
        break;
    }

    if(portNumber==-1)
    {
      connectString = "Database=" + alias;
    }
    else
    {
      connectString = "Server=" + server + ":" + portNumber +
                      ";Database=" + alias;
    }

    if(userId != "")
    {
      connectString += ";UID=" + userId + ";PWD=" + password;
    }

    DB2Connection conn = new DB2Connection(connectString);
    conn.Open();
    Console.WriteLine("  Connected to the " + alias + " database");
    return conn;

  } // ConnectDb

So the first thing that I was drawn to was the use of a string array to pass in the values used to build the connection string.  Now I'm no expert, but isn't the use of overloaded functions the better way to do this?  If that won't work for you, it's also possible to use a function with defaulted parameters.  Every one of the cases in the switch statement defaults the values exactly the same if they aren't provided which would make either of those three options viable.

You could argue that the example is using the .NET 2.0 parameter array feature, but the .NET Native Provider, as of the time this was written, does not support .NET 2.0 so why would they show it.  If that is what they are trying to do then they should at least make a statement to that fact in the sample code.  Heck the code doesn't even say what version of the .NET Framework it is written to.

This type of shit pisses me off.  Some straight out of school newbie who, through no fault of their own, reads this sample on the web and now they think that this is the way the world should work.  Then they show up on my project and I have to unlearn them, which usually happens only after you find code like this in a code review, and then point them down the road know to be straight and narrow.

I know that some other blogger has hammered a company (Macromedia if I remember correctly) for similar sample code best practices infractions.  If this is what reputed companies are putting out as sample code, it's no wonder that we have some much crap code out there keeping the sites by Jeff and Alex active.

DbType and other provider specific types

At work I've been working with a couple of my very skilled co-workers (on who is a DB2/Cobol programmer, but I don't hold that against him) to try to solve a problem in our data access layer.  Recently the IT department began a project to upgrade their DB2 servers from version 7.2 to 8.1.  As stated by the lead on that upgrade project, "There will be no problems in the upgrade process."  Yah, right.  Short version is that of course there were issues.  The rest of that story should be told over a couple more drinks than I have in me right now.

Part of our debugging/research/stabs-in-the-dark today led us (well, one of the other guys, not me) down the path of database typing for command object parameters.  As our code exists today we are programming to interfaces.  IDbCommand, IDbDataParameter, IDataReader.  Things of that sort.  As a part of the IDbDataParameter code we are possibly, depending on the constructor overload you use, working with the DbType enumeration.  It is not required, but if you feel the need, you can dictate the exact type of the parameter being passed to your stored procedure or parameterized query.  In our case we're working with the stored procedures, but I don't think that this is a factor.

I decided to take a look around the DB2 native provider (IBM.Data.DB2.dll for those of you that care to follow along) code using Lutz Roeder's Reflector.  My was I surprise at what I saw.  First, the DB2 native provider implements the IDbDataParameter interface on the DB2Parameter class as one would expect.  What I didn't expect was that there was both a DbType and a DB2Type property on the DB2Parameter class.  When I started poking around in it I noticed that there were a number of different types in the DB2Type enumeration so I decided to take a look through the SqlClient and OracleClient classes to see if the same exists and to my surprise they do!

Because our code is using the DbType enumeration we can't benefit from the full range of data types provided by the DB2 provider.  Perhaps this is the root of our problems?  I'll update you if we find out.

Published at

Future Desktop Replacement

I'm not usually that big on new fangled gidgets and widgets, but I saw this out on the web today and I'm stoked at the possibility that this desktop replacement may actually get built. Watch the video and go to the BumpTop website to find out more.

Give me this and a tablet PC any day.

Published at

User Group Podcast

I stumbled on this podcast from Australia tonight that discusses the state of User Groups there and in New Zealand.  It's a pretty good podcast, but it's a shame that the audio for Adam Cogan is sketchy at best.

Published at

SQL Server Session State Mode over a non-standard port

For the past week I've been working on a change to an application at work.  Some 'enterprisey' person decided that we needed a central session state management scheme and SQL Server Mode was the silver bullet.  Not only did it give the IT department another way to throw the word Enterprise into their functionality reports, but it was an easy, low impact change.

The project (apparently this change did demand project status) kicked off and a few weeks of emails went around before anyone would even tell us if the database had been created.  At one point a DBA noted that the database creation was on his list and "...should take too long (3 to 4 hours)".  Amazing considering that the script to do all this work usually only takes about 30 seconds to run in query analyzer, but I'm not a DBA so what do I know.

After being apprised of the database creation, we started changing our web.config files using the information that we were provided.  Immediately things didn't work.  Any page that used session state threw the following exception details.

System.Data.SqlClient.SqlException: Invalid connection.

We fought with this for a while before a long string of emails started to get fired around.  After a few days of playing Pass-The-Email we were told that the SQL Server had been configured to use a port other than the default and that this was most likely our problem.  It took another week of relentless research (which turned nothing up) and a meeting of epic attendance to determine the cause of the problems.

If you need to hook up your web servers to a SQL Server that is not using the default port for communication you will need to use the following sqlConnectionString format.

data source=MySqlServerName,99999;user id=<myusername>;password=<mypassword>;

The key to note here is that you separate the SQL Server Name from the port number with a comma.  We thought it would be with a colon, but alas we were wrong.

Published at

I'm turning into a boolean bigot

I'm going to the top of the mountain (cause there's so many here in Edmonton) and I'm going to shout it loud.  In my little programming world I'm turning into a boolean bigot.  So many things in the world are based on boolean values (day/night, on/off, yes/no) and yet I'm starting to find the use of true/false in code to be meaningless.  I can hear the naysayers all around the world screaming profanities interlaced with my name and that of my sled dog team.  Since none of you will trust me on this, I'm going to have to explain.

People will argue that booleans are necessary to show the state of a more complex time (i.e. Object.Active = true).  If you re-read that last sentence you will notice that the argument is about the use for object state, not whether it is active/inactive.  In this example active/inactive represent the state.  Why wouldn't we move towards code that used enumerations and would read like this:

Object.State = State.Active

To me there are a number of benefits to the use of an enumerated value set.  For me, this code is clearer when read for the first time.  This is keeping in step with the tenet that all code should read like a book.  It also provides you with the ability to expand the number of states that objects have without ever breaking any code (I've seen this done enough to know how painful it is to go from true/false to true/false/somtimestrue).

That last argument is not the strongest one that I can make for using enumerations over booleans.  How about this instead.  Have you ever started to walk through some code that you've never seen before and you come across that one function/method call that has 6 parameters, most of which are booleans, and you can't tell what the heck each parameter does?  Take a look at this code and tell me what the parameters represent.

string SomeStringManipulation(strInput, true, false, true, true, false)

So with your knowledge of that line of code, what does that 3rd boolean (the 'true' value) do?  See the problem?  Imagine how this would look in my world full of boolean bigots.  Sigh...fine, I'll show you an example.

string SomeStringManipulation(strInput, Casing.Sensitive, Capitalization.Lower, Spelling.Check, Grammar.Check, BadWordFilter.Off)

I don't know about you, but if I were to come across this code in amongst a couple hundred thousand lines of other stuff, I would know straight off what it was trying to do.  It reads much more like proper language (English in this case) than the first example.  That alone should be the litmus test that you use when writing code.  If you can't read it to someone on the other end of the phone and have them understand what the code is trying to do, you need to rethink how it looks and reads.

The one argument that I can hear a number of people making right now is that each of those parameters are now enumerations and enumerations require more coding.  Well whoopdee-doo.  Tell me that not investing the time up front to use this as a standard was worthwhile once you're 6 months into a maintenance gig, you have the client breathing down your neck, the code isn't working, you've never seen it before and you come face to face with a list of true/false values.

Property Event Pattern

I know someone else smarter than me has probably written a post, an article or a book on this, but I'm going to put it up here anyways.

Tonight I was screwing around with some code for a small side project (also known as experimentation in a real world domain) and I figured that I needed to have a couple of classes fire events every time that any of their properties changed.  I've done this kind of thing before in my glorious VB6 past, but I hadn't had the need nor opportunity in C#.  I figured I would take the time to document it here so that I wouldn't forget it and, as you'll see in a second, so that I could download the files easily.

The Pattern

        public delegate void ChangingHandler(object sender, PropertyChangingArgs args);

        public delegate void ChangedHandler(object sender, PropertyChangedArgs args);


        public event ChangingHandler NameChanging;

        public event ChangedHandler NameChanged;

 

        private string _name;

        public string Name

        {

            get

            {

                return _name;

            }

            set

            {

                PropertyChangingArgs changingArgs = new PropertyChangingArgs(Name, value);

 

                if (NameChanging != null)

                {

                    NameChanging(this, changingArgs);

                }

                if (changingArgs.Cancel == false)

                {

                    _name = value;

 

                    PropertyChangedArgs changedArgs = changingArgs;

                    if (NameChanged != null)

                    {

                        NameChanged(this, changedArgs);

                    }

                }

            }

        }

Supporting Classes

    public class PropertyChangedArgs : EventArgs

    {

        public PropertyChangedArgs()

        {

        }

 

        public PropertyChangedArgs(object beforeValue, object afterValue)

        {

            this.BeforeValue = beforeValue;

            this.AfterValue = afterValue;

        }

 

        private object _beforeValue = new object();

        public object BeforeValue

        {

            get

            {

                return _beforeValue;

            }

            set

            {

                _beforeValue = value;

            }

        }

 

        private object _afterValue = new object();

        public object AfterValue

        {

            get

            {

                return _afterValue;

            }

 

            set

            {

                _afterValue = value;

            }

        }

    }

    public class PropertyChangingArgs : PropertyChangedArgs

    {

        public PropertyChangingArgs()

        {

        }

 

        public PropertyChangingArgs(object beforeValue, object afterValue)

            : base(beforeValue, afterValue)

        {

        }

 

        private bool _cancel = false;

        public bool Cancel

        {

            get

            {

                return _cancel;

            }

 

            set

            {

                _cancel = value;

            }

        }

    }

The Implementation

        public void LoadPage()

        {

            Equipment equip = new Equipment();

            equip.NameChanged += new ChangedHandler(NameChanged);

            equip.NameChanging += new ChangingHandler(NameChanging);

        }

 

        private void NameChanged(object sender, PropertyChangedArgs args)

        {

            int i = 1;

        }

 

        private void NameChanging(object sender, PropertyChangingArgs args)

        {

            int i = 1;

        }

In the end I created a block of code and supporting classes that has a pre-change (Changing) and post change (Changed) event for a property.  The pre-change event has a parameter of PropertyChangingArgs with a Cancel property.  Setting that property equal to true will cancel the update of the property value.  Nice to do if you set your validation to be executed in the pre-change event and the validation fails.

Once I got the code written for the first property on the class I was working with, I proceeded to start manually writing the code for each of the other properties (about 25 in all).  I quickly realized that this was both boring and error prone so I decided to delve into Visual Studio 2005's Code Snippet functionality to speed the process.  You can find my code snippets, complete with the two supporting 'Args' classes here (download).  All you have to do to add the two snippets to the IDE is copy the two files to the following folder

My Documents\Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets

Because the delegates only need to appear once per class, I have created those as a separate code snippet.  Once you've copied the files the two code snippets will appear in intellisense as prope (creates the property with the event code) and propedelg which creates the two delegate lines that appear at the top of the Pattern section of this post.  To use the code that the snippets generate you will need to include the two 'Args' classes either in the same project that the code is being generated in or in a project that is referenced.

Published at

New Blog

Instead of cluttering up this blog with information about my favourite recipes I've decided to create a new blog dedicated to food called Geek Tukka.  I'm hoping to keep this up to date with recipes, wine commentary and restaurant reviews.

You'll also notice that I'm using WordPress to host the blog.  I figured that I'd heard enough praise from Scoble that I should go and see what it's all about.  So far I'm reasonably impress, although I've found the blog management interface a little difficult to locate information in.  Mostly this is because WordPress uses different nomenclature than I'm used to.  Now that I have it configured the way I want, I'm probably not going to end up in it much as I will be posting with Windows Live Writer.

Don't fear, this blog will not go unattended, and I'm certainly not switching focus.

Published at

Edmug Event Feeds

At one of our Edmug board meetings recently we discussed making announcements for our events available in a syndicated format.  Prior to the DNIC tour event with John Bristowe on September 7th, John and I were talking and he said that we should look at making our events available in iCalendar format.  Today I was playing around with these ideas and found that Google Calendar offers the ability to publish your calendar in both formats.

What does this mean to you, the rabid Edmug attendee?  You can now subscribe to our Events Feed in your favourite RSS aggregator here. You can also subscribe to our iCalendar feed here.

So how can you use the iCalendar feed?  Apparently Outlook 2007 will have native support for the iCalendar format, but we live in today don't we?  The easiest way I have found to make this useful is to download and install Remote Calendars from SourceForge.  This is a tool that was written using VSTO and integrates right into Outlook.  Once you have the iCalendar feed configured in Remote Calendars, it will poll, either on demand or each time you open Outlook, the feed and make entries into your Outlook Calendar.  I've set this up for myself and it works really well.

Leave me a comment if you want to know more about setting up for our feeds, or if you have ideas for more feeds that Edmug can provide.

Published at

Chicken Enchiladas

Another recipe that I absolutely love.  This one is a little better suited to cooler days than a hot summer afternoon, but I've had it in both and it's very, very good in either.

Ingredients
1 lb Chicken (boned thighs or breasts will work just fine) cut in stir fry sized pieces
4-6 large (10-12") tortillas
3 tbsp dry oregano
1 medium onion (I prefer white, but yellow works just fine too)
350 grams of grated mozzarella cheese
1 bottle taco sauce (approximately 215 ml)
hot peppers to taste. Pickled jalapenos or canned smoked chipotles work very well.

Instructions
Sweat onions in a frying pan at medium high heat until they are translucent.  Add the meat to the frying pan.  Add the oregano making sure to get the meat evenly covered.  When the meat is fully cooked remove the frying pan from heat and let the ingredients cool.

Put a light coat of the taco sauce (only use about 10% of the sauce) on the bottom of an oven safe dish. Place some of the ingredients from the frying pan onto a tortilla. Add hot peppers to the tortilla. Roll the tortilla into a burrito style package and place in the oven dish. Once all the ingredients from the frying pan have been wrapped in tortillas and placed in the oven dish side by side, cover the tops of them with the remaining taco sauce. Put the grated mozzarella on top of the taco sauce.

Put the dish in a pre-heated oven at (350 degrees) for 20 minutes. At the end switch the oven to the broil setting and prop the oven door open for approximately 5 minutes or until the cheese has sufficiently colored.

Remove the dish from the oven and serve 2 to 3 people.

The start of the Fall extravaganza...and it's all free

Yes, you read right.....free.  Free like the wind.  Free like open source.  Free like Justice doing his Sound of Music dance routine.

soundofmusic

Now that you've spent a couple minutes trying to eradicate that image from your mind, I'll tell you more about the free stuff.  We have 3 major Edmug events happening here in Edmonton (4 if you count the start of the NHL pre-season) in the month of September.

Sept. 7th, 2006:  John Bristowe is presenting on ASP.NET ATLAS at 6pm in the Centennial room at the Milner Library.

Sept 27th, 2006:  Jean-Paul Boodhoo is presenting on something of your choice (vote here now!) at 6pm in the Centennial room

Sept 30th, 2006:  Edmonton Code Camp gets into full swing at the Milner Library at 9am and runs all day.  There will be two rooms running presentations through out the day on a variety of topics.  Register here as space is limited.

It's going to be a great September if you're a developer in Edmonton and surrounding area.  Drop in on one or more of these events and pick up some knowledge with a possible side order of swag.  I promise that we'll keep Justice from dancing, but I can't promise he won't be wearing the dress.

Published at

Called out by Mrs. L.

So I got called out by Mrs. Loquacious last week.  Apparently I don't write enough human interest pieces on this blog for her liking.  Well, maybe after this post she'll regret the fact that I ever wrote one.

So here are the 8 things that Mrs. L. never wanted to know about me.

  1. I'm sarcastic.  I leave you to determine if the rest of this post is employing any sarcasm.  If you can provide the right identification (leave a comment) to the points employing sarcasm *and* you're single, female (sorry Justice) and even remotely close to my igloo I will get back to you in a snap.
  2. I love to cook.  It could be anything from barbeque to home-made pasta.  I love simple food, not because there's less work involved, but because I think that simple food tastes great.  One of my dreams is to be able to take a year or two off of work and go to a really good cooking school.  I don't want to do this as a career change, but rather as a personal journey where I can learn and practice with passion.
  3. I love to eat.  Thank goodness for number two on this list because I love to eat what I think is quality food.  I don't get any enjoyment from eating fast food or chain restaurant meals.  I love food from one-off establishments or, better yet, home cooked.  My favourite style of food would probably be Mexican, but you wouldn't find me choosing any one type of food over another on many occasions.
  4. I read a lot.  I find that I flip from reading only novels for a few months to reading nothing but technical books for a few months.  Regardless, I will read just about anything.
  5. I enjoy teaching technology people about technology.  It's a passion of mine that I'm starting to re-explore this area in a more professional way than I have before.  Teaching and spreading knowledge is one of the biggest reasons that I'm participating in the operation of the Edmonton .NET User Group.
  6. Traveling is something that I love to do.  When most people say this they mean that they enjoy traveling to exotic places abroad.  Although I enjoy that type of traveling, I think that too many people look past the natural and social wonders that we have here in Canada.  I think the BC Kootenays are one of my favourite places in the world and one day I'll move out there and ply my trade (plumbing by that point I'm sure).
  7. In 1988 I participated in the Olympic Torch Relay for the Calgary Winter Olympics.  I carried the torch through the entire town of Cache Creek (yes, it really is that small).  I was featured on the front page of the Kamloops Daily News and in the Vancouver Sun or Province (I can't remember which).
  8. In 1997 I finished 3rd at the Canadian College Rodeo Finals in the bull riding.  I was riding one week after having surgery on my arm to insert a plate and seven screws to repair a broken ulna.  I rode bulls for close to three years and got on about 200 bulls in that time.  I never was good enough riding to make it to the Calgary Stampede as a contestant, but I did visit emergency rooms in Olds, Red Deer, Taber, Lethbridge, Dawson Creek and Beaverlodge.  Emergency room nurses are great, but I think I'll try to meet them a different way than on a gurney.

I'll now give you a bonus point in non-point format.  I don't forward spammy emails.  I'm going to make the same rule here.  Mrs. L, I've answered this so that I don't have to be harassed by you on this subject (and because it was a little fun too), but I'm not tagging anyone else.