web-dev-qa-db-fra.com

String.Equals () ne fonctionne pas comme prévu

J'utilise LINQ pour rechercher dans l'une de mes tables Entity Framework et trouver un "groupe" basé sur le nom. Le nom est une chaîne et semble être Unicode (dit qu'il est dans l'edmx). J'ai une méthode GetGroup() et je passe un nom à rechercher. Débogage via le code, j'ai déjà un groupe nommé "Test" dans ma base de données. Une fois que je passe dans un groupe nommé "TEST", je m'attends à ce qu'il renvoie le "Test" qui était déjà dans la base de données. Il pour une raison quelconque, ne trouve pas le "Test" et pense que "TEST" n'existe pas. Voici ma requête, je ne vois pas pourquoi cela ne fonctionne pas. Veuillez aider.

"nom" est le passé dans le nom du groupe. Ma .Equals ne semble fonctionner que si le gr.Name et le nom sont exactement les mêmes. Si un caractère est en majuscule dans l'une des deux chaînes, les .Equals ne fonctionnent pas. J'ai essayé d'utiliser InvariantCultureIgnoreCase, et cela n'a pas semblé aider. Au cas où quelqu'un le demanderait, les MyLeagueId et LeagueId correspondraient toujours, la base de données est configurée pour qu'il puisse y avoir un groupe dans un identifiant de ligue différent. Je ne pense pas que ce soit le problème.

Group g = (from gr in this.DatabaseConnection.Groups
           where gr.Name.Equals(name, StringComparison.OrdinalIgnoreCase) &&
           gr.LeagueId == this.MyLeagueId
           select gr).FirstOrDefault();
40
Travyguy9

Lorsque vous utilisez LINQ to Entities, il le convertira automatiquement en LINQ to SQL. Et si le champ de base de données sur lequel vous effectuez un .Equals n'a pas d'assemblage de NOCASE (SQLite dans mon exemple), il sera toujours sensible à la casse. En d'autres termes, la base de données définit comment faire la comparaison de chaînes plutôt que le code.

42
Travyguy9

La comparaison des chaînes avec StringComparison.OrdinalIgnoreCase fonctionne en mémoire ou avec IEnumerable<T>. Vous essayez de l'utiliser avec IQueryable<T>, mais le fournisseur de votre requête ne le comprend pas.

Cela fonctionne pour moi:

db.Users.FirstOrDefault(
     s => s.Username.Equals(username, StringComparison.OrdinalIgnoreCase)
);
35
Swapnil Malap

J'ai fait quelques recherches. Tu ne peux pas faire. Le classement (le type de comparaison) est défini au niveau de la colonne du tableau. Vous ne pouvez pas le modifier via EF. S'il est défini comme insensible à la casse, toutes les recherches seront insensibles à la casse. S'il est défini comme sensible à la casse, alors votre seul espoir est ToUpper() les chaînes.

http://connect.Microsoft.com/VisualStudio/feedback/details/435783/entity-framework-conceptual-model-doesnt-support-string-equals-via-linq

http://social.msdn.Microsoft.com/Forums/en/adodotnetentityframework/thread/3810aa67-f6fe-4624-a14b-eaaa0e05ddcd

EF4 Linq Oracle11g rendant les requêtes non sensibles à la casse

comparaison sensible à la casse LINQ to Entities

9
xanatos

Utilisez la String.Compare() car elle peut être traduite en SQL.

Ici sont quelques exemples de correspondance de chaînes dans Linq, avec la traduction Sql également.

9
Jowen

J'aime la réponse de TravyGuy d'un point de vue technique. Pour une réponse plus directe et pratique, essayez d'utiliser:

string.Compare(string A, string B, StringComparison.OrdinalIgnoreCase) == 0
5
AlvinfromDiaspar

Essayez name.Equals(gr.Name, StringComparison.OrdinalIgnoreCase)

Si cela fonctionne, le problème pourrait être avec gr.Name.

--- Éditer ---

Je suppose que gr.Name n'est pas de type System.string. (puisque String.Equals vous donne une erreur ==> du post précédent)

donnez-lui un coup de feu

(gr.Name as string).Equals(name, StringComparison.OrdinalIgnoreCase)

ou

String.Equals((gr.Name as string), name, StringComparison.OrdinalIgnoreCase)
2
Viv