2013-10-26 3 views
15

Auf der Grundlage der Antwort auf diese Frage:Case-Insensitive String-Vergleich funktioniert nicht in C#?

How can I do a case insensitive string comparison?

Ich versuche, ein Groß- und Kleinschreibung Vergleich zu tun, ohne die Vergleichs oder ToLower mit:

var user = db.Users.FirstOrDefault(s => String.Equals(s.Username, username, StringComparison.OrdinalIgnoreCase)); 

Jedoch habe ich einen Fehler:

Incorrect number of arguments supplied for call to method 'Boolean Equals(System.String, System.String, System.StringComparison)'

Was mache ich falsch?

+0

Haben Sie diesen Benutzernamen überprüft und s.username sind vom Typ String. – Tilak

+1

Ziemlich sicher L2S unterstützt diese bestimmte Methode nicht. Wenn dies tatsächlich ausführbarer C# -Code wäre und nicht etwas, das von einem Abfrage-Provider übersetzt wird, wäre es in Ordnung. – Servy

+0

Warum versuchen Sie, string.Compare zu vermeiden? – tsells

Antwort

33

Der String-Vergleich mit StringComparison.OrdinalIgnoreCase funktioniert im Speicher oder mit IEnumerable<T>. Sie versuchen, es mit IQueryable<T> zu verwenden, aber der Provider Ihrer abfragbaren versteht es nicht.

In Linq-to-Sql sollten Sie in der Lage sein SqlMethods.Like(s.UserName, userName) zu verwenden, wie folgt aus:

var user = db.Users.FirstOrDefault(s => SqlMethods.Like(s.UserName, userName)); 

SqlMethods ist im System.Data.Linq.SqlClient Namespace.

Die Like Methode ist case-insensitive, so sollten Sie das erwartete Ergebnis erhalten.

EDIT : I tried and get "LINQ to Entities does not recognize the method Boolean Like(System.String, System.String) method, and this method cannot be translated into a store expression."

Dies scheint mit EF (link) ein bekanntes Problem zu sein.

This works for me:

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

Es scheint, dass, obwohl EF schwer übersetzen die statische Equals zu SQL hat, ist es kein Problem Equals übersetzen die Instanz hat. Dies ist ein sehr guter Fund - es macht eine leicht lesbare, performante Lösung.

Sie könnten auch eine einfachere Methode, mit ToUpperCase oder ToLowerCase, verwenden aber das kann Abfrage-Optimierer verwenden Indizes verhindern:

// Warning: this may not perform well. 
var user = db.Users.FirstOrDefault(s => s.UserName.ToUpperCase() == userName.ToUpperCase()); 
+1

Danke dafür. Ich habe versucht und bekomme "LINQ to Entities erkennt die Methode 'Boolean Like (System.String, System.String)' Methode nicht, und diese Methode kann nicht in einen Store-Ausdruck übersetzt werden." - Gedanken? – SB2055

+0

Das funktioniert für mich: db.Users.FirstOrDefault (s => s.Username.Equals (Benutzername, StringComparison.OrdinalIgnoreCase)); Ich weiß nicht, was ich in Bezug auf die Auswahl einer Antwort tun soll - fühlen Sie sich frei, dies zu notieren, und ich kann Ihre abchecken? – SB2055

+0

Würden Sie sagen, dass mit der Lösung, die ich im Kommentar gepostet habe, etwas nicht in Ordnung ist? Ich war auf der Suche nach einer einfachen, performanten Lösung, die den Best Practices folgt. – SB2055