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
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");
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(...);
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));
@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 ?
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.
@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 .
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".
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.
I walk through the differences between client-eval and passing pointers to SQLite in my SQLite & EF Core: UDF all the things! post.
@bricelam Can this be closed?
Yep. @John0King feel free to continue the conversation here even though the issue is closed.
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
Most helpful comment
Also note, SQLite only performs case-insensitive comparisons of ASCII characters. Override the default to include all Unicode characters: