80
public Articles GetByName(string name, Categories category, Companies company)
{
    var query = from article in session.Linq<Articles>()
                where article.Name == name &&
                      article.Category == category &&
                      article.Company == company
                select article;
    return query.FirstOrDefault();
}

how can query be case insensitive. I can use toLower or toUpper but i want with OrdinalIgnoreCase. Is it possible?

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
senzacionale
  • 20,448
  • 67
  • 204
  • 316
  • Possible duplicate of [LINQ Contains Case Insensitive](http://stackoverflow.com/questions/3360772/linq-contains-case-insensitive) – Rowland Shaw Jan 09 '17 at 09:03

8 Answers8

119

Use String.Equals with the appropriate parameters to make it case insensitive

mySource.Where(s => String.Equals(s, "Foo", StringComparison.CurrentCultureIgnoreCase));
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • hmm now i get Value cannot be null. Parameter name: left – senzacionale Mar 15 '11 at 14:08
  • 2
    Are you sure? `String.Equals` should be able to accept null as a parameter. – Adam Rackis Mar 15 '11 at 14:11
  • if i use toUpper then i get Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index. works only the code i paste... – senzacionale Mar 15 '11 at 14:16
  • 2
    FirstOrDefault is probably returning null, which you might be using without first checking. Break up your code a bit and make certain that String.Equals is what's failing, because, again, String.Equals should be able to accept null as a parameter – Adam Rackis Mar 15 '11 at 14:16
  • What kind of error? `FirstOrDefault()` returns null if the LINQ statement doesn't match any results. – Edgar Mar 15 '11 at 14:17
  • It sounds like you have some other problem with your query. You need to gather your code and ask a new question. – Adam Rackis Mar 15 '11 at 14:18
  • I've having the same problem as @senzacionale, consuming an IQueryable object generated by NHibernate. I wonder if it's an NHibernate problem? – Jonathan Apr 03 '11 at 09:19
  • 2
    Possibly. NH's Linq parser might be confused by String.Equals? Just to be sure, you're using String.Equals(s1, s2) and not str.Equals(str2), right? – Adam Rackis Apr 03 '11 at 14:42
62

Instead of == use the .Equals(name, StringComparison.OrdinalIgnoreCase) method.

var query = from article in session.Linq<Articles>()
            where article.Name.Equals(name, StringComparison.OrdinalIgnoreCase) &&
                  article.Category.Equals(category) &&
                  article.Company.Equals(company)
            select article;

return query.FirstOrDefault();
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
Edgar
  • 4,348
  • 4
  • 40
  • 59
  • 12
    Please take care with String.Equals() and StringComparison in combination with LINQ. Depending on the database system the option could be ignored. E.g. SQLite or Oracle. – StefanG Feb 14 '14 at 10:42
28

If this is a LINQ to SQL query against a database with a case-insensitive collation, then it already is case-insensitive. Remember that LINQ to SQL isn't actually executing your == call; it's looking at it as an expression and converting it to an equality operator in SQL.

If it's LINQ to Objects, then you can use String.Equals as the other posters have pointed out.

John Bledsoe
  • 17,142
  • 5
  • 42
  • 59
9
var query = from article in session.Linq<Articles>()
           where string.Equals(article.Name,name, StringComparison.OrdinalIgnoreCase) &&
                 string.Equals(article.Category,category, StringComparison.OrdinalIgnoreCase) &&
                 string.Equals(article.Company,company, StringComparison.OrdinalIgnoreCase)
                        select article;

            return query.FirstOrDefault();

It will also handle when Name,Category,Company is null

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
Stecya
  • 22,896
  • 10
  • 72
  • 102
  • 2
    This particular solution isn't necessarily supported. For example using Linq2SQL, on SQLServer2008: `Method 'Boolean Equals(System.String, System.String, System.StringComparison)' has no supported translation to SQL.` similarly: `'Boolean Equals(System.String, System.StringComparison)' has no supported translation to SQL.` – mcdrewski Nov 20 '12 at 23:30
  • @mcdrewski I actually get `Incorrect number of arguments supplied for call to method 'Boolean Equals(System.String, System.String, System.StringComparison)'` even when I'm _clearly_ providing the expected arguments. Using EF4 I think, probably a bug. – drzaus Feb 26 '16 at 14:30
  • 1
    @drzaus go with Edgar's answer using the Equals method off the property rather than static one from the type. – CF5 Feb 19 '20 at 09:03
7

Use

String.Equals(article.Name, name, StringComparison.OrdinalIgnoreCase)
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • 2
    Huh - never used `OrdinalIgnoreCase` before - what's the difference between that and `CurrentCultureIgnoreCase`? – Adam Rackis Mar 15 '11 at 13:45
  • @Adam Racks: RTFM ;) Basically, your solution takes into account comparison rules of the current culture, while mine does a simple byte by byte comparison after making both strings upper case. A google or SO search will bring up a lot of info on that topic. – Daniel Hilgarth Mar 15 '11 at 13:48
6

If you are using C# 6.0 you can define a short extension method to be used when constructing LINQ statements:

public static bool EqualsInsensitive(this string str, string value) => string.Equals(str, value, StringComparison.CurrentCultureIgnoreCase);

Usage:

query.Where(item => item.StringProperty.EqualsInsensitive(someStringValue));

For C# less than 6.0 it will look like this:

public static bool EqualsInsensitive(this string str, string value) 
{
    return string.Equals(str, value, StringComparison.CurrentCultureIgnoreCase);
}
Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164
0

Change it to

public Articles GetByName(string name, Categories category, Companies company)
        {
    var query = from article in session.Linq<Articles>()
                            where string.Equals(article.Name, StringComparison.CurrentCultureIgnoreCase)  == name &&
                                string.Equals(article.Category, StringComparison.CurrentCultureIgnoreCase == category &&
                                string.Equals(article.Company, StringComparison.CurrentCultureIgnoreCase == company
                            select article;

                return query.FirstOrDefault();
}
Chad
  • 23,658
  • 51
  • 191
  • 321
0

Use string.Equals(name, article.Name, StringComparison.OrdinalIgnoreCase) when you are sure that your database supports it.

E.g. SQLite with a collate of NOCASE will ignore the option. Oracle uses session settings NLS_COMP, NLS_SORT that will be taken.

Else use ToLower() or ToUpper() when you have no culture issues.

StefanG
  • 1,234
  • 2
  • 22
  • 46