web-dev-qa-db-fra.com

LINQ contient insensible à la casse

Ce code est sensible à la casse, comment le rendre insensible à la casse?

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM.Where(fi => fi.DESCRIPTION.Contains(description));
}
166
Jeaf Gilbert
fi => fi.DESCRIPTION.ToLower().Contains(description.ToLower())
235
Nealv

Si la requête LINQ est exécutée dans un contexte de base de données, un appel à Contains() est associé à l'opérateur LIKE:

.Where(a => a.Field.Contains("hello")) devient Field LIKE '%hello%'. L'opérateur LIKE est insensible à la casse par défaut, mais cela peut être changé avec changer le classement de la colonne .

Si la requête LINQ est exécutée dans un contexte .NET, vous pouvez utiliser IndexOf () , mais cette méthode n'est pas prise en charge dans LINQ to SQL.

LINQ to SQL ne prend pas en charge les méthodes qui prennent un paramètre CultureInfo, probablement parce qu'il ne peut pas garantir que le serveur SQL gère les cultures de la même manière que .NET. Ce n'est pas tout à fait vrai, car ne supporte que StartsWith(string, StringComparison).

Cependant, elle ne semble pas prendre en charge une méthode qui évalue LIKE dans LINQ to SQL et une comparaison insensible à la casse dans .NET, rendant impossible la méthode cohérente Contains ().

112
Sjoerd

En supposant que nous travaillions avec des chaînes ici, voici une autre solution "élégante" utilisant IndexOf().

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM
        .Where(fi => fi.DESCRIPTION
                       .IndexOf(description, StringComparison.OrdinalIgnoreCase) != -1);
}
62
Jeff Mercado

La réponse acceptée ici ne mentionne pas le fait que si vous avez une chaîne nulle, ToLower () lève une exception. Le moyen le plus sûr serait de faire:

fi => (fi.DESCRIPTION ?? string.Empty).ToLower().Contains((description ?? string.Empty).ToLower())
11
Marko

En utilisant C # 6.0 (qui autorise les fonctions d'expression et la propagation null), pour LINQ to Objects, cela peut être fait en une seule ligne comme ceci (en vérifiant également la valeur null):

public static bool ContainsInsensitive(this string str, string value) => str?.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0;
5
Alexei

IndexOf fonctionne mieux dans ce cas

return this
   .ObjectContext
   .FACILITY_ITEM
   .Where(fi => fi.DESCRIPTION.IndexOf(description, StringComparison.OrdinalIgnoreCase)>=0);
4
Menelaos Vergis

Vous pouvez utiliser string.Compare

    lst.Where(x => string.Compare(x,"valueToCompare",StringComparison.InvariantCultureIgnoreCase)==0);

si vous voulez juste vérifier contient alors utilisez "Tous"

  lst.Any(x => string.Compare(x,"valueToCompare",StringComparison.InvariantCultureIgnoreCase)==0)
4
Code First
public static bool Contains(this string input, string findMe, StringComparison comparisonType)
{
    return String.IsNullOrWhiteSpace(input) ? false : input.IndexOf(findMe, comparisonType) > -1;
}
1
E Rolnicki

StringComparison.InvariantCultureIgnoreCase faites le travail pour moi:

.Where(fi => fi.DESCRIPTION.Contains(description, StringComparison.InvariantCultureIgnoreCase));
0
Yanga