2012-07-10 15 views
5

Wir haben mehrere Projekte in VB.Net, die .Net Framework 4 und Linq to Entities für viele unserer SQL-Abfragen verwenden. Der Wechsel zu EF ist für uns eine neue Schicht (seit ca. 4-6 Monaten) und hat die Unterstützung des oberen Managements, weil wir so viel schneller programmieren können. Wir verwenden immer noch viele gespeicherte Procs, aber wir führen diese auch über Linq zu Entitäten aus.VB.Net Linq zu Entitäten Null Vergleich - "Ist nichts" oder "= Nichts"?

Ich hoffe, etwas Verwirrung zu klären, und ich kann keine direkte Antwort finden, die Sinn ergibt. Wir haben einige Abfragen, wo wir Datensätze haben wollen, wo ein bestimmtes Feld einen NULL-Wert hat. Dies sind einfache Auswahlabfragen, keine Aggregate oder links beitritt, usw. Microsoft empfiehlt die Abfrage in etwa so aussehen MSDN Link:

dim query = from a in MyContext.MyTables 
Where a.MyField = Nothing 
Select a 

Ich habe mehrere Projekte, bei denen ich genau das tun und es funktioniert super, keine Warnungen in der IDE . Kürzlich wurde ein neues Projekt von einem anderen Entwickler erstellt und als er seine Nullprüfung wie oben durchführte, erhalten wir alle diese Warnung in der IDE:

Warnung 1 Dieser Ausdruck wird immer zu Nothing ausgewertet (aufgrund der Nullverbreitung vom Gleichheitsoperator)). Um zu überprüfen, ob der Wert null ist, sollten Sie "Is Nothing" verwenden.

Beim Vergleichen der Projekte sind die Option explizit und die Option strikt aktiviert. Wenn wir die Warnung ignorieren, erhalten wir den genauen Datensatz, nach dem wir suchen, wenn die App ausgeführt wird. Die Warnung verschwindet, wenn ich das = Zeichen zu IS ändere. Aber warum erschien diese Warnung in einem Projekt und nicht in anderen? Es ist verwirrend, wenn es sogar auf MSDN Beispiele gibt, die den Gleichheitsoperator verwenden.

+0

VB.NET LINQ hat auch das Schlüsselwort "Equals". Ich habe keine Möglichkeit, es zu testen, aber vielleicht versuchen Sie es stattdessen? 'Where a.MyField Equals Nothing' –

+0

@Cory: Es ist ein kontextabhängiges Schlüsselwort, das nur in' Join'-Klauseln (AFAIK) verwendet wird. Ich glaube nicht, dass du es irgendwo anders benutzen kannst. –

Antwort

2

Ich glaube, was Sie hier sehen, ist, dass MyField ein Nullable(Of T) Typ ist. Wahrscheinlich ein primitives Integer, Single, etc ...

Der Grund, warum Sie diese Warnung ist zu sehen ist, weil der Compiler den normalen Gleichheitsoperator für den Urtyp auf die Nullable(Of T) Version fördert. Sie führt im Wesentlichen die folgenden

Dim myField As Integer? = a.MyField 
Dim other As Integer? = Nothing 
If myField = other Then 
... 
End If 

Das Problem ist aber, dass, wenn Integer? den Wert Nothing hat, wird es nicht zu irgendetwas gleich vergleichen. Daher wird die obige Klausel Where immer False zurückgeben. Der Compiler versucht, Sie vor dieser problematischen Ecke von Nullable(Of T) zu warnen und Sie zu einer Is Nothing Prüfung zu bringen, die bestimmt, ob a.MyField einen Wert ungleich Null hat.

Dieser Blog-Artikel hat eine sehr detaillierte Erklärung, warum diese Warnung generiert wird und all die Mechanik dahinter. Der Artikel ist für C# geschrieben, aber die Grundvoraussetzung gilt auch für VB.Net.

+0

Wenn ich also dieses Recht verstehe, funktionierte das Gleichheitszeichen in einer Abfrage, weil das Feld keine Nullwerte enthalten konnte, aber in einer anderen Abfrage ein Problem darstellte, da es nullfähig ist und daher die unterschiedliche Syntax erfordert. –

+0

@ChrisJones korrekt. Normalerweise können Sie '=' mit einem Nullwert verwenden. Der Vergleich mit 'Nothing' wird jedoch immer' False' zurückgeben, so dass der Compiler eine Warnung darüber ausgibt – JaredPar

+0

Ich kann mit etwas mehr tun = Nothing, um Felder zu stringeln, die in der Datenbank nullbar sind, aber nicht die anderen Daten Typen und kann entweder Is Nothing oder das HasValue-Mitglied, das Afshin erwähnt hat, verwenden. Danke, dass Sie etwas Licht ins Dunkel gebracht haben. –

5

generiert Spalte sollte ein Nullable(Of T)

werden, so können Sie überprüfen, ob das Feld Wert hat oder nicht so:

dim query = from a in MyContext.MyTables 
Where Not a.MyField.HasValue 
Select a 
+0

Ich habe dies bei mehreren Datentypen versucht und es würde nicht bei String-Werten funktionieren. Ich konnte das HasValue-Member für Nullable-Integer-, -Date- und boolesche Datentypen verwenden. –

0

Mindestens in LINQ zu Objekten Sie können dies stattdessen verwenden:

Nullable(Of Integer).Equals(a, b) 

Dies funktioniert gut mit beiden, keiner oder keiner der beiden Werte ist nichts.