Ich validiere Benutzername (Groß-und Kleinschreibung nicht) und Passwort (Groß-und Kleinschreibung) aus der Datenbank
Ich verwende Entity Framework 5.0 zur Interaktion mit der Datenbank
In der Datenbank ist das Passwort
"0x11A46971EFF1E1A2CA228CF592CA37DC77E7CCF759602D53629C22B693AEEE96CCD9F889D8E9A92C19391E6BD2DD07E741E9B7AA07E391ACDC939B993C9D7F5D"
Ich erwarte null als Gegenleistung für meinen folgenden Codeblock, wenn ich die Groß- / Kleinschreibung des Passwortes auf niedriger setze, d. h.
"0x11a46971eff1e1a2ca228cf592ca37dc77e7ccf759602d53629c22b693aeee96ccd9f889d8e9a92c19391e6bd2dd07e741e9b7aa07e391acdc939b993c9d7f5d"
aber es schlägt nicht fehl und gibt die richtige Benutzereinheit zurück.
%Vor%Während, wenn ich alle Benutzer bekomme und dann vergleiche gibt es eine korrekte Ausgabe, d. h. user == null
%Vor%Das ist seltsam? Warum passiert es? Wie schreibe ich Groß-und Kleinschreibung sensible Abfrage von LINQ zu SQL?
Bei der SQL-Suche wird nicht zwischen Groß- und Kleinschreibung unterschieden. Wenn Sie ToList
zuerst eingeben, wird eine Groß- und Kleinschreibung berücksichtigt. Aber der ToList
wird alles aus der DB zurückgeben. Stattdessen führen Sie die Where
auf der db und dann einen weiteren Vergleich, um sicherzustellen, dass das Passwort der richtige Fall ist.
SQL unterscheidet nicht zwischen Groß- und Kleinschreibung. Wenn Sie sich das generierte SQL ansehen, sieht es etwa so aus:
%Vor%Es wird unabhängig vom Fall wahr zurückgegeben. Das zweite Beispiel ruft ToList auf, so dass es jetzt einen .net String vergleicht, was Groß- und Kleinschreibung unterscheidet.
Bei Verwendung von
%Vor%Sie arbeiten an einer Lazyloaded EntityCollection. Da SQL nicht zwischen Groß- und Kleinschreibung unterscheidet, wird es jedes Mal als wahr zurückgegeben.
Wenn Sie
verwenden %Vor% Sie wechseln von LINQ To Entities
zu LINQ To Objects
, sodass Sie jetzt einen Vergleich zwischen Groß- und Kleinschreibung vornehmen können.
Der große Nachteil ist, dass jedes Mal, wenn Sie ToList()
verwenden, Ihre Query sofort ausgeführt wird und Sie die COMPLETE-Liste der Benutzer aus der Datenbank laden.
Wie schon erwähnt, liegt das daran, dass Ihre Datenbank so konfiguriert ist, dass sie Groß- und Kleinschreibung nicht vergleicht. Das folgende kleine Programm zeigt, wie EF die an StringComparison
übergebenen String.Equals
Werte vollständig ignoriert. Es zeigt auch, wie das Ändern der Sortierung der Datenbankspalte das erreicht, was Sie brauchen.
Dies ist ein wichtiges Konzept beim Arbeiten mit EF (und anderen LINQ-Anbietern). Ihre Abfrage, wie sie geschrieben wird sieht wie normaler .NET-Code aus. Es ist jedoch nicht! Viele Anbieter übersetzen den Code in etwas völlig anderes, in diesem Fall SQL (für SQL Server, Transact-SQL). Nur eine Untermenge der verfügbaren .NET-Methoden funktioniert überhaupt (weshalb Sie zum Beispiel Regex
in einer EF-Abfrage nicht verwenden können), und diejenigen, die funktionieren, weisen möglicherweise ein subtil anderes Verhalten auf als das, was Sie tun würden erwarten.
Wenn Sie ToList()
für eine Abfrage verwenden, dann Ihren Filter anwenden, verwenden Sie LINQ to Objects, nicht EF, um den Filter anzuwenden. LINQ to Objects ist "real" .NET, so dass Sie die gesamte Palette von .NET-Funktionen zur Verfügung haben. Natürlich verlieren Sie den Vorteil, dass Ihr Code auf dem SQL Server ausgeführt wird, daher ist dies normalerweise keine Option.
Hier gibt es eine ausführlichere Antwort:
Bei Bedarf können Sie die Spalte auf der Serverseite so konfigurieren, dass Groß- und Kleinschreibung beachtet wird. Aber in Ihrem Fall sehe ich nicht, warum Sie das Passwort überhaupt abfragen müssen. Sicherlich gibt es nur ein Passwort für jeden Benutzernamen, und ein Benutzername sollte nicht zwischen Groß- und Kleinschreibung unterscheiden. Warum also nicht einfach nach dem Benutzernamen suchen und dann das Passwort auf dem Ergebnis überprüfen?
Wie alle anderen bereits erwähnt haben, liegt die Ursache des Problems darin, dass SQL Server standardmäßig keine Groß- und Kleinschreibung berücksichtigt und C # standardmäßig Groß- und Kleinschreibung berücksichtigt.
Sie können das Kennwortfeld von varchar
nach varbinary
ändern, um dieses Problem zu umgehen.
Warum die anonymen Stimmen runter? Die Verwendung einer Zeichenfolge zum Speichern und Vergleichen eines scheinbar 64-Byte-Hashwerts ist nicht der beste Ansatz. Es ist nicht notwendig, einen Hash zu codieren, um ihn zu speichern (es sei denn Entity Framework kann damit nicht umgehen?).
Tags und Links .net c# entity-framework lambda