Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use case-insensitive query with Sqlite provider ? #11414

Closed
John0King opened this issue Mar 24, 2018 · 17 comments
Closed

How to use case-insensitive query with Sqlite provider ? #11414

John0King opened this issue Mar 24, 2018 · 17 comments
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported

Comments

@John0King
Copy link

I'm not sure if I remember wrongly,
I see the COLLATE NOCASE append in the sql query very long time ago (may be not COLLATE NOCASE,but something else , all I remember is my query is case insensitive),

but recently I use Sqlite again , and it is case sensitive , and I can not compare an "Email" filed with x.Email == myvariable

@bricelam
Copy link
Contributor

Some users have been successful by configuring the property like this: (although it's certainly not how the API was intended to be used)

modelBuilder.Entity<X>().Property(x => x.Email).HasColumnType("TEXT COLLATE NOCASE");

@bricelam
Copy link
Contributor

bricelam commented Mar 26, 2018

Currently, the only way to do it per-query (not configuring the column) is by using raw SQL:

db.X.FromSql($"SELECT * FROM X WHERE Email = {myvariable} COLLATE NOCASE").Where(...);

@bricelam
Copy link
Contributor

Also note, SQLite only performs case-insensitive comparisons of ASCII characters. Override the default to include all Unicode characters:

var connection = (SqliteConnection)db.Database.GetDbConnection();
connection.CreateCollation("NOCASE", (x, y) => string.Compare(x, y, ignoreCase: true));

@John0King
Copy link
Author

@bricelam thanks a lot,
but, I don't understand your last code, what is SqliteConnection.CreateCollation() ?
and may I ask , does Sqlite "case-insensitive" in EF 1.x ?

@bricelam
Copy link
Contributor

bricelam commented Mar 27, 2018

The last code listing uses SQLite's ADO.NET APIs (the layer beneath EF Core) to replace SQLite's built-in NOCASE comparison with .NET's more complete implementation. (using pure unicorn magic 🦄)

Yes, my first two comments also apply to EF Core 1.x.

@John0King
Copy link
Author

@bricelam Thanks again.

to replace SQLite's built-in NOCASE comparison with .NET's more complete implementation.

Is that because Sqlite's ADO.Net provider is also the database engine so it can do that ? otherwise AFAK doing comparison in "client" side is pointless .

@bricelam
Copy link
Contributor

SQLite is an in-process database. The snippet above works by passing a function pointer to SQLite that it can use to invoke the lambda. So technically, it is happening "on the server".

@bricelam
Copy link
Contributor

bricelam commented Mar 28, 2018

This is different from EF's client-evaluated queries where extra data may be retrieved from the server so additional processing can be done on the client before returning the final result set.

@bricelam
Copy link
Contributor

I walk through the differences between client-eval and passing pointers to SQLite in my SQLite & EF Core: UDF all the things! post.

@ajcvickers
Copy link
Contributor

@bricelam Can this be closed?

@bricelam
Copy link
Contributor

Yep. @John0King feel free to continue the conversation here even though the issue is closed.

@bricelam bricelam added the closed-no-further-action The issue is closed and no further action is planned. label Mar 28, 2018
@nbelley
Copy link

nbelley commented Jan 21, 2020

Quick question, when should I execute the code:

var connection = (SqliteConnection)db.Database.GetDbConnection();
connection.CreateCollation("NOCASE", (x, y) => string.Compare(x, y, ignoreCase: true));

And, is it enough or I also need to use the .HasColumnType("TEXT COLLATE NOCASE"); trick?

If I do it in the OnModelCreating I get a CreateCollation can only be called when the connection is open. execption

@TMendys
Copy link

TMendys commented Feb 22, 2022

I have had luck with using EF.Functions.Like() and it works. You add the property and the searchstring like this: EF.Functions.Like(person.LastName, $"%{searchString}%").

@roji
Copy link
Member

roji commented Feb 22, 2022

For anyone seeing this, since this issue was opened, EF Core added support for collations - see this page.

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
@fineboy0407
Copy link

Great! I've learned something new.
Thanks for your efforts.

@winstond
Copy link

I set a collation for a column to "NOCASE" and confirmed in SQLiteStudio that it was set properly.
However when doing a .Where, I'm still finding the results are coming back case sensitive (If I search for "a" I don't get things that have "A").
Is that an issue with .Where?

@roji
Copy link
Member

roji commented Oct 13, 2023

@winstond please open a new issue with a minimal, runnable repro so we can see what exactly you're doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported
Projects
None yet
Development

No branches or pull requests

8 participants