2009-12-05 4 views
5

Je lis des explications contradictoires sur les comparaisons de chaînes Linq à Sql.Linq to Sql égalité insensible à la casse

Quand je fais ce qui suit:

from p in db.People 
    where p.UserName=username 
    select p 

nom d'utilisateur = "JOhn"

je reçois le cas correct résultat insensible. Est-ce que Linq le fait par défaut ou cela se passe-t-il dans la base de données SQL?

+0

Vous manquez des citations? La modification de la casse des noms de variables n'affecte pas les résultats. –

+0

ce n'est pas ce que je voulais dire voir ci-dessus – zsharp

Répondre

4

Je pense que vous obtenez des résultats contradictoires en fonction de ce que votre variable db pointe vers et où la comparaison est réellement exécutée. Si c'est le cas, linq construira la requête et l'enverra au serveur SQL. Il semble que vous pouvez forcer insensible à la casse en appelant

where p.UserName.ToLower()=username.ToLower() 
+1

Désolé, mais c'est un mauvais conseil. p.UserName.ToLower() = username.ToLower() traduira en une requête SQL qui forcera une analyse complète de la table. Cela n'a pas d'importance si la table "people" est petite, mais s'il s'agit d'une grande table, elle ne pourra pas utiliser d'index pouvant couvrir la colonne 'username'. – KristoferA

1

Cela dépend de la base de données. SQL Server 2008 traite les chaînes comme insensibles à la casse, y compris lorsqu'elles sont utilisées dans une expression d'index. Linq ne fait pas ça.

Lecture on MSDN ou this article.

+2

La sensibilité/insensibilité à la casse dépend du classement utilisé dans votre base de données et/ou les colonnes impliquées (par défaut, SQL Server est installé, mais il peut être ignoré à plusieurs endroits le niveau de la colonne). – KristoferA

3

Votre exemple de requête se traduira par quelque chose à peu près comme ceci:

sélectionnez [t0] .col1, [t0] .col2, ..., [ t0] .coln de [schéma]. [les gens] où [t0] .UserName = @ p0

... la valeur de la variable nom d'utilisateur sera transmis dans le @ p0 variable sql. En tant que tel, la sensibilité à la casse, la sensibilité à l'accent, etc. est contrôlée par le classement que vous avez configuré votre instance SQL Server/db/table/colonne à utiliser. S'il n'est spécifié nulle part ailleurs, le classement par défaut des DB ou de l'instance de base de données est utilisé, mais le classement peut être spécifié jusqu'au niveau de la colonne.

La plupart des gens exécutent SQL Server avec des classements insensibles à la casse (CI) mais comme je l'ai dit plus haut, il peut être remplacé dans la base de données, il suffit de vérifier le classement. Contrairement à la requête L2O (linq to objects), dans ce cas, la sensibilité à la casse est la valeur par défaut et vous devez la rendre insensible à la casse en utilisant le remplacement string.equals qui vous permettent de spécifier la culture et/ou l'insensibilité à la casse ...

+0

ne pas utiliser un remplacement string.equals avoir le même problème que vous avez commenté avec mon résultat? Forcer tous les enregistrements à venir sur le côté linq pour faire la comparaison? –

+0

@Jeff, La référence string.equals était juste une comparaison entre le comportement de L2S et de L2O, désolé si je n'étais pas clair sur ce point. Mais oui, si vous combinez les deux et que vous effectuez l'évaluation du côté client sous la forme d'une requête L2O, vous obtiendrez non seulement tous les enregistrements, mais également les enverrez sur le réseau. En d'autres termes, l'utilisation de la bonne collation est la clé ici. L'exemple de votre réponse sera toujours évalué dans la base de données, mais avec le surcoût supplémentaire d'un balayage de table en raison de l'encapsuleur de fonction sur le côté gauche où le prédicat de clause. – KristoferA

+0

Merci pour la réponse (j'ai donné +1 quand j'ai fait le commentaire précédent) –