Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework core - Contains is case sensitive or case insensitive?

"Contains" in Entity Framework core should equivalent to the SQL %like% operator. Therefore "Contains" should be case insensitive however it is case sensitive! (at least in postgres????)

The following only outputs a result when the correct casing for keyword is used.

context.Counties.Where(x => x.Name.Contains(keyword)).ToList(); 

What am I doing wrong?

like image 493
001 Avatar asked Apr 07 '17 12:04

001


People also ask

Is EF core case sensitive?

For one thing, EF Core does know not which case-sensitive or case-insensitive collation should be used. More importantly, applying a collation would in most cases prevent index usage, significantly impacting performance for a very basic and commonly-used .

Is SQL Server case-insensitive?

SQL Server is, by default case insensitive; however, it is possible to create a case sensitive SQL Server database and even to make specific table columns case sensitive. The way to determine a database or database object is by checking its “COLLATION” property and look for “CI” or “CS” in the result.

Which COLLATION is case-insensitive?

A case-insensitive collation ignores the differences between uppercase and lowercase letters for string comparison and sorting, whereas a case-sensitive collation does not. For example, in case-insensitive collation, “A” and “a” are equal.

Which features are not supported in EF core?

However, there are some features of EF 6 which are not supported in EF Core 2.0 such as: EDMX/ Graphical Visualization of Model. Entity Data Model Wizard (for DB-First approach) ObjectContext API.

Is 'contains' in Entity Framework case insensitive?

"Contains" in Entity Framework core should equivalent to the SQL %like% operator. Therefore "Contains" should be case insensitive however it is case sensitive! (at least in postgres????) The following only outputs a result when the correct casing for keyword is used. context.Counties.Where (x => x.Name.Contains (keyword)).ToList ();

Is'contains'case insensitive?

Therefore "Contains" should be case insensitive however it is case sensitive! (at least in postgres????) The following only outputs a result when the correct casing for keyword is used. What am I doing wrong? It used to be the case for older versions of EF core.

Is string contains case sensitive in EF?

It used to be the case for older versions of EF core. Now string.Contains is case sensitive, and for exemple for sqlite it maps to sqlite function `instr ()' ( I don't know for postgresql).

Is IQueryable case insensitive or case insensitive?

IQueryable.Where is executed in the database, so it is most likely to be case insensitive. IEnumerable.Where uses C# String.Contains, so it is case sensitive. Behaviour of IQueriable would depend on the database. For example, in SQL server it would be case insensitive but for postgres it's case sensitive


2 Answers

It used to be the case for older versions of EF core. Now string.Contains is case sensitive, and for exemple for sqlite it maps to sqlite function `instr()' ( I don't know for postgresql).

If you want to compare strings in a case-insensitive way, you have DbFunctions to do the jobs.

context.Counties.Where(x => EF.Functions.Like(x.Name, $"%{keyword}%")).ToList(); 

UPDATE to @Gert:

A part of the assumption in the question is incorrect. string.Contains does NOT convert into a LIKE expression even though it USED to be the case in ef core versions <= 1.0 (I think).

  • In SQLServer string.contains converts into CHARINDEX(), in oracle and sqlite into instr() which are case sensitive by default UNLESS db or column collation is defined otherwise ( Again, I don't know for postgresql ).
  • In all cases EF.Functions.Like() converts into a SQL LIKE expression which is case-insensitive by default unless db or column collation is defined otherwise.

So yes it all goes down to collation but - correct me if I'm wrong - in a way the code can have an influence on the case-sensitive/insensitive search depending on which one of the above method you use.

Now, I might not be completely up to date but I don't think EF core migrations deal with DB collation naturally and unless you've already created the table manually you will end up with the default collation (case-sensitive for sqlite and I honestly don't know for the others).

Getting back to the original question you have at least 2 options to perform this case-insensitive search if not 3 in a future release :

  1. Specify the column collation on creation using DbContext.OnModelCreating() using this trick
  2. Replace your string.Contains by EF.Functions.Like()
  3. Or wait for a promising feature still in discussion : EF.Functions.Collate() function
like image 51
DarkUrse Avatar answered Oct 02 '22 03:10

DarkUrse


My answer will concern NpgSQL.

  1. EF.Functions.Like() in PostgreSQL is case-sensitive, but you can use EF.Functions.ILike() extension method located in Npgsql.EntityFrameworkCore.PostgreSQL assembly.

  2. If you don't have reference to Entity Framework assembly in place where you build query, you can use combination ToLower() and Contains() methods, because Npgsql is able translate ToLower() method to correct SQL

Example:

context.Counties.Where(x => x.Name.ToLower().Contains(keyword.ToLower())).ToList(); 

About second method keep in mind: you may have performance problems and may encounter problems associated with encoding.

like image 21
Stas Boyarincev Avatar answered Oct 02 '22 04:10

Stas Boyarincev