rickgaribay.net

Space shuttles aren't built for rocket scientists, they're built for astronauts. The goal isn't the ship, its the moon.
posts - 275, comments - 169, trackbacks - 33

My Links

News

Where's Rick?

Windows 8 Unleashed, Microsoft Tempe, 11/2
AzureConf, Channel 9 Studios, 11/14
Desert Code Camp, 11/17
VS Live! Las Vegas, 3/25-3/29
VS Live! Chicago, 5/13 - 5/16


About Me
I am a developer, architect, writer and speaker, passionate about distributed .NET technologies and Application Lifecycle Management. I am currently the General Manager of the Connected Systems Practice at Neudesic.





    follow me on Twitter



    Archives

    Post Categories

    Published Works

    String Comparison Gotcha

    I was burning the midnight oil last night writing some samples for a project I’m working on with Azure AppFabric Service Bus Queues and Topics. In short, I was modifying some existing code I had written to defensively check for the existence of a queue so that I could avoiding entity conflicts when attempting to create the same queue name twice.

    Given a queueName of “Orders”, the first thing I did was to check to see if it exists by using the Client API along with a very simple LINQ query:

      1: var qs = namespaceClient.GetQueues();
    
      2: 
    
      3: var result = from q in qs
    
      4: 
    
      5: where q.Path == queueName
    
      6: 
    
      7: select q;

     

    If the result came back as empty, I’d go ahead and create the queue:

      1: if (result.Count() == 0)
    
      2: {
    
      3: 
    
      4:      Console.WriteLine("Queue does not exist");
    
      5: 
    
      6:     // Create Queue
    
      7: 
    
      8:     Console.WriteLine("Creating Queue...");
    
      9: 
    
     10:     Queue queue = namespaceClient.CreateQueue(queueName);
    
     11: 
    
     12: }

     

    This code worked fine the first time, since the queue did not exist, but the next time I ran the code, and each time following, Line 10 above would execute each time because the result.Count() was always zero.

    Looking at the queue properties, it was clear that the queue name was stored in lower case, regardless of the case used in my queueName variable:

    image

    On the surface, this created an interesting dilemma: Even though case didn’t matter when creating the queue, when I was searching for the queue name in Line 5 of my LINQ query, it was always resulting in a false match. Could this be a bug?

    My first thought was to go back and make queueName lowercase, changing to “orders”. This fixed the problem on the surface, but it felt dirty and fragile.

    After reviewing the code with some colleagues (thanks @clemensv and @briannoyes) it turns out that I had made an esoteric, but key error when checking for equality of the queue path:

    where q.Path == queueName

     

    The full explanation is available on the C# Programming Guide on MSDN, but in a nutshell, I had made the error of using the “==” operator to check for equality. From MSDN: “Use basic ordinal comparisons when you have to compare or sort the values of two strings without regard to linguistic conventions. A basic ordinal comparison (System.StringComparison.Ordinal) is case-sensitive, which means that the two strings must match character for character: "and" does not equal "And" or "AND".”

    The solution was to modify the where clause to use the Equals method which takes the object you are comparing to along with a StringComparison rule of StringComparison.OrdinalIgnoreCase:

      1: var result = from q in qs
    
      2:      where q.Path.Equals(queueName,StringComparison.OrdinalIgnoreCase)
    
      3: select q;

     

    Explanation from MSDN: “A frequently-used variation is System.StringComparison.OrdinalIgnoreCase, which will match "and", "And", and "AND". StringComparison.OrdinalIgnoreCase is often used to compare file names, path names, network paths, and any other string whose value does not change based on the locale of the user's computer.”

    The AppFabric team is doing exactly the right thing since the queue path corresponds to a network path.

    Here is the full code, which allows me to check for the existence of the queue path ensuring that I am ignoring case and the rest is as it was:

      1: var qs = namespaceClient.GetQueues();
    
      2: 
    
      3: var result = from q in qs
    
      4:              where q.Path.Equals(queueName,StringComparison.OrdinalIgnoreCase)
    
      5:              select q;
    
      6:             
    
      7: if (result.Count() == 0)
    
      8: {
    
      9:    Console.WriteLine("Queue does not exist");
    
     10: 
    
     11:    // Create Queue
    
     12:    Console.WriteLine("Creating Queue...");
    
     13:    Queue queue = namespaceClient.CreateQueue(queueName);
    
     14: }

     

    When you’ve been programming for a while, it’s sometimes easy to forget the little things, and it is often the least obvious things that create the nastiest bugs. 

    Hope this saves someone else from having a Doh! moment like I did Smile

    Print | posted on Wednesday, August 10, 2011 4:08 PM | Filed Under [ Azure Service Bus 1.5 ]

    Comments have been closed on this topic.

    Powered by: