2012-07-10 26 views
5

Abbiamo diversi progetti in VB.Net, utilizzando .Net Framework 4 e Linq alle entità per molte delle nostre query SQL. Passare a EF è un nuovo cambiamento per noi (lo stiamo usando da circa 4-6 mesi) e ha il sostegno del management superiore perché possiamo codificare molto più velocemente. Usiamo ancora molti proc memorizzati, ma li eseguiamo anche attraverso Linq alle Entities.VB.Net Linq alle entità Null Comparison - 'Is Nothing' or '= Nothing'?

Spero di chiarire un po 'di confusione e non riesco a trovare una risposta diretta che abbia senso. Abbiamo alcune query in cui vogliamo record in cui un campo specifico ha un valore NULL. Si tratta di semplici query di selezione, non aggregati o sinistra raccordi ecc Microsoft consiglia la query simile a questa MSDN Link:

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

Ho diversi progetti in cui faccio esattamente questo e funziona benissimo, nessun avviso nell'IDE . Di recente un nuovo progetto è stato creato da un altro sviluppatore e tutti gli abbiamo ricevuto questo avviso nell'IDE:

Avviso 1 Questa espressione sarà sempre valutata su Nothing (a causa della propagazione null dall'operatore di uguaglianza). Per verificare se il valore è nullo, considerare l'uso di 'Is Nothing'.

Confrontando i progetti, l'opzione esplicita e l'opzione rigorosa sono attivi per ognuno. Se ignoriamo l'avviso, otteniamo il set di record esatto che stiamo cercando quando viene eseguita l'app. L'avviso scompare se cambio il segno = su IS. Ma perché questo avvertimento appare in un progetto e non in altri? È confuso quando anche su MSDN ci sono esempi che utilizzano l'operatore di uguale.

+0

VB.NET LINQ ha anche la parola chiave 'Equals'. Non ho un modo per testarlo, ma forse provarlo? 'Dove a.MyField è uguale a Niente' –

+0

@Cory: È una parola chiave contestuale che viene utilizzata solo nelle clausole' Join' (AFAIK). Non penso che tu possa usarlo da nessun'altra parte. –

risposta

2

Credo che quello che state vedendo qui è che MyField è un tipo Nullable(Of T). Probabilmente un primitivo Integer, Single, ecc ...

Il motivo che stai vedendo questo avviso è perché il compilatore promuove l'operatore di uguaglianza normale per il tipo primitivo alla versione Nullable(Of T). Esegue essenzialmente i seguenti

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

Il problema però è che quando Integer? ha il valore Nothing non confronterà uguale a niente. Quindi la clausola Where sopra riportata restituirà sempre False. Il compilatore sta tentando di avvisarti di questo angolo problematico di Nullable(Of T) e di inviarti a un controllo Is Nothing che determinerà se a.MyField ha un valore non nullo.

Questo articolo del blog contiene una spiegazione molto dettagliata del motivo per cui viene generato questo avviso e di tutti i meccanismi che lo seguono. L'articolo è scritto per C# ma la premessa di base è applicabile anche a VB.Net.

+0

Quindi, se ho capito bene, il segno di uguale ha funzionato in una query perché il campo non era annullabile ma era un problema in un'altra query perché è annullabile, quindi richiede la sintassi diversa. –

+0

@ChrisJones corretti. Normalmente puoi usare '=' con un valore nullable. Il confronto con 'Nothing' però restituirà sempre' False' anche se il compilatore emette un avvertimento a riguardo – JaredPar

+0

Giocando con questo un po 'di più, posso fare = Niente per stringare campi che sono annullabili nel database, ma non gli altri dati tipi e può utilizzare Is Nothing o il membro HasValue di cui Afshin ha parlato. Grazie per aver fatto luce su questo. –

5

colonna generata dovrebbe essere un Nullable(Of T)

in modo da poter controllare se quel campo ha un valore o meno in questo modo:

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

Ho provato questo su diversi tipi di dati e non avrebbe funzionato su valori stringa. Sono stato in grado di utilizzare il membro HasValue su valori numerali integer, data e tipi di dati booleani. –

0

Almeno in LINQ to Objects è possibile utilizzare questo invece:

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

Questo funziona perfettamente con entrambi, o nessuno dei due valori è Niente.