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 - 303, comments - 180, trackbacks - 35

My Links

News

Where's Rick?


AgileAlliance deliver:Agile 2019- 4/29
Desert Code Camp, PHX - 10/11
VS Live Austin, TX - 6/3
VS Live SF - 6/17


About Me
Hands on leader, developer, architect specializing in the design and delivery of distributed systems in lean, agile environments with an emphasis in continuous improvement across people, process and technology. Speaker and published author with 18 years' experience leading the delivery of large and/or complex, high-impact distributed solutions in Retail, Intelligent Transportation, and Gaming & Hospitality.

I'm currently a Principal Engineer at Amazon, within the North America Consumer organization leading our global listings strategy that enable bulk and non-bulk listing experiences for our WW Selling Partners via apps, devices and APIs.

Full bio

Note: All postings on this site are my own and don’t necessarily represent the views of my employer.



Check out my publications on Amazon Kindle!





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: