12

I'm reading a username and then checking to see if exists in another database table, the problem is whilst the username is the same the case maybe different and is preventing it from finding a match example jsmith and JSmith or JSMITH.

How can I fix this? Should I lower the case when writing to the first database or can I alter my code below when I'm comparing the two?

drUser["Enrolled"] = 
    (enrolledUsers.FindIndex(x => x.Username == (string)drUser["Username"]) != -1);

UPDATE:

Still struggling with this, the code below compiles but doesn't give the correct result, when viewing enrolled users I see those that aren't enrolled, when viewing those that are not enrolled I see 1 that is enrolled but their username case is the same in each datababse. Have I formatted the code below correctly?

drUser["Enrolled"] = (enrolledUsers.FindIndex(x => x.Username.Equals((string)drUser["Username"], StringComparison.OrdinalIgnoreCase)));

Thanks Jamie

Jamie
  • 2,465
  • 10
  • 28
  • 31
  • 1
    Dang, I was too slow. Thought it would be appropriate for me to answer this one.. ;) – jsmith Jun 25 '10 at 15:17
  • 1
    @SLaks his example name.. is my user name.. :) – jsmith Jun 25 '10 at 15:21
  • @Jamie: When I am faced with code that seems like it should work, but does not, then I find it helpful to decompose it and check all my assumptions. I.e. Does Equals() do what you expect when you compare two strings (like mentioned below culture settings can make a difference). If that works, then check if FindIndex works on an exact match. etc. etc. – Andre Artus Jun 25 '10 at 16:45
  • You may want to use something like Exists(), see my answer below. – Andre Artus Jun 25 '10 at 16:47
  • It's worth noting that for some character sets it is more efficient to convert to upper case instead of lower. Also, this exactly the kind of thing stored procedures are for. – 3Dave Jun 25 '10 at 18:11
  • @David: And for other character sets the opposite is true. In ASCII lowercase == uppercase | 0x20. So if you want to check whether a character falls in the range 'A-Za-z' you can do "(ch | 0x20) in ['a-z'])". Of course if you want to code a ToUpper routine then you should check to see if it is in range first before modifying it. But it will probably not work for other character sets, so unless you can guarantee your data avoid it. I ran a little test converting chars with culture sensitive library functions for Upper and Lower and both ran through a million in a fraction of a second. – Andre Artus Jun 25 '10 at 18:36

5 Answers5

21

You need to cal the Equals method, which takes a StringComparison parameter.

For example:

x.Username.Equals((string)drUser["Username"], StringComparison.OrdinalIgnoreCase)

If x.Username can be null, you should call the static Equals method:

String.Equals(x.Username, (string)drUser["Username"], StringComparison.OrdinalIgnoreCase)

Otherwise, x.Username.Equals can throw a NullReferenceException.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Sorry to sound thick but the code below doesn't work correctly, it compiles but doesn't find the matching users. drUser["Enrolled"] = (enrolledUsers.FindIndex(x => x.Username.Equals((string)drUser["Username"], StringComparison.OrdinalIgnoreCase))); – Jamie Jun 25 '10 at 15:32
  • Just tried the update, and this doesn't compile. Where am I going wrong? drUser["Enrolled"] = (enrolledUsers.FindIndex(String.Equals(x.Username, (string)drUser["Username"], StringComparison.OrdinalIgnoreCase))); – Jamie Jun 25 '10 at 15:39
  • Please edit your question and add your exact code. – SLaks Jun 25 '10 at 15:54
3

The preferred way to do this, is to specify the string comparison by using something like

string.Equals(x.Username, (string)drUser["Username"], StringComparison.OrdinalIgnoreCase

to do the equality check, instead of "=="

Rob Levine
  • 40,328
  • 13
  • 85
  • 111
0

How about using ToUpper().

 if(!(dr["Enrolled"] == null || dr["Username"] == null))
 {
    if(dr["Enrolled"].ToString().ToUpperInvariant()== dr["Username"].ToString().ToUpperInvariant())
    {
        //Do Something
    }
}
MikeTWebb
  • 9,149
  • 25
  • 93
  • 132
  • please provide a reason for the down vote. I'd like to learn why this code is a bad practice. Thanks – MikeTWebb Jun 25 '10 at 16:10
  • I didn't downvote you, but I can guess why. Firstly, this will explode if either value is null. Secondly, this is not culture aware. It may work for English (and lots of other languages too), but not all. The oft-quoted example is "The Turkish Case": http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html .Net gives you culturally aware string comparisons for free - use them! – Rob Levine Jun 25 '10 at 16:31
  • Far out....thanks for the explanation. Much appreciated. Yeah, as far as the NULLs....the code example wasn't intended to be bullet proof. I always check for NULLs. – MikeTWebb Jun 25 '10 at 16:48
  • Side note: `ToUpperInvariant` would be your way to go then. – sunside Jun 25 '10 at 16:57
  • 1
    As a side note, ToUpper also creates a whole new string, which is extra overhead. It isn't a big deal for a little string here or there, but if you are doing a lot of comparisons it seems a bit wasteful to create a temporary just to do the compare. – Dolphin Jun 25 '10 at 18:53
0

Have you tried this?

string userName = (string)drUser["Username"];
bool enrolled = enrolledUsers.Exists(x =>
  string.Equals(x.Name, userName, StringComparison.CurrentCultureIgnoreCase));

Is there a reason you are using FindIndex instead?

Andre Artus
  • 1,850
  • 15
  • 21
0

try the string.compare method. all overloads

Or a more specific one

If nothing else, I hope it educates.

paul
  • 50
  • 8