web-dev-qa-db-fra.com

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

"Contient" dans le noyau Entity Framework doit être équivalent à l'opérateur SQL% like%. Par conséquent, "Contient" doit être insensible à la casse mais il est sensible à la casse! (au moins en postgres ????)

Ce qui suit ne produit un résultat que lorsque la casse correcte pour le mot clé est utilisée.

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

Qu'est-ce que je fais mal?

18
001

C'était le cas pour les anciennes versions d'EF core. Maintenant string.Contains Est sensible à la casse, et par exemple pour sqlite, il est mappé à la fonction sqlite `instr () '(je ne sais pas pour postgresql).

Si vous souhaitez comparer des chaînes de façon insensible à la casse, vous disposez de DbFunctions pour effectuer les tâches.

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

MISE À JOUR vers @Gert:

Une partie de l'hypothèse de la question est incorrecte. string.Contains Ne se convertit PAS en un LIKE expression Même s'il UTILISÉ pour être le cas dans les versions de base ef <= 1.0 (je pense).

  • In SQLServerstring.contains Se transforme en CHARINDEX(), en Oracle et sqlite en instr() qui sont sensibles à la casse par défaut SAUF db ou le classement des colonnes est défini autrement (encore une fois, je ne sais pas pour postgresql).
  • Dans tous les cas, EF.Functions.Like() se convertit en une expression SQL LIKE qui est insensible à la casse par défaut, sauf si le classement de la base de données ou des colonnes est défini autrement.

Donc, oui, tout se résume à la collation, mais - corrigez-moi si je me trompe - d'une certaine manière, le code peut avoir une influence sur la recherche sensible à la casse/insensible en fonction de l'une des méthodes ci-dessus que vous utilisez.

Maintenant, je ne suis peut-être pas complètement à jour, mais je ne pense pas que les migrations de base EF traitent naturellement du classement DB et à moins que vous n'ayez déjà créé la table manuellement, vous vous retrouverez avec le classement par défaut (sensible à la casse pour sqlite et moi honnêtement, je ne sais pas pour les autres).

Pour revenir à la question d'origine, vous avez au moins 2 options pour effectuer cette recherche insensible à la casse sinon 3 dans une version future:

  1. Spécifiez le classement des colonnes lors de la création à l'aide de DbContext.OnModelCreating () à l'aide de cette astuce
  2. Remplacez votre string.Contains Par EF.Functions.Like()
  3. Ou attendez une fonctionnalité prometteuse encore dans discussion : EF.Functions.Collate() fonction
20
DarkUrse

Ma réponse concernera NpgSQL.

  1. EF.Functions.Like() dans PostgreSQL est sensible à la casse, mais vous pouvez utiliser l'extension EF.Functions.ILike()méthode située dans Npgsql.EntityFrameworkCore.PostgreSQLAssembly .

  2. Si vous n'avez pas de référence à Entity Framework Assembly où vous générez la requête, vous pouvez utiliser les méthodes de combinaison ToLower() et Contains(), car Npgsql est able translate ToLower() méthode pour corriger SQL

Exemple:

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

À propos de la deuxième méthode, gardez à l'esprit: vous pouvez avoir des problèmes de performances et rencontrer des problèmes associés au codage.

5
Stas Boyarincev

IQueryable.Where est exécuté dans la base de données, il est donc très probablement insensible à la casse.

IEnumerable.Where utilise C # String.Contains, il est donc sensible à la casse.

Lisez cette réponse: Retourner IEnumerable vs IQueryable

4
Kfir Guy

Essayez-le:

Vous pouvez Lower case champ et valeur de recherche

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

Ou tu peux Upper Case classé et valeur de recherche

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