2012-07-10 20 views
5

Tenemos varios proyectos en VB.Net, utilizando .Net Framework 4 y Linq to Entities para muchas de nuestras consultas SQL. Mudarse a EF es un cambio nuevo para nosotros (lo hemos usado durante aproximadamente 4-6 meses) y tiene el respaldo de la administración superior porque podemos codificar mucho más rápido. Todavía usamos muchos procs almacenados, pero incluso los ejecutamos a través de Linq to Entities también.VB.Net Linq a las entidades Comparación nula - 'Is Nothing' o '= Nothing'?

Espero aclarar algo de confusión y no puedo encontrar una respuesta directa que tenga sentido. Tenemos algunas consultas donde queremos registros donde un campo específico tiene un valor NULL. Estas son las consultas de selección simple, sin agregados o izquierda se une, etc. Microsoft recomienda la consulta mirada algo como esto MSDN Link:

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

Tengo varios proyectos en los que hacer exactamente esto y funciona muy bien, no hay advertencias en el IDE . Recientemente, otro desarrollador creó un proyecto nuevo y cuando hizo su verificación nula como la anterior, todos recibimos esta advertencia en el IDE:

Advertencia 1 Esta expresión siempre evaluará a Nothing (debido a la propagación nula del operador equals) Para verificar si el valor es nulo, considere usar 'Is Nothing'.

Comparando los proyectos, la opción explícita y la opción estricta están activadas para cada uno. Si ignoramos la advertencia, obtenemos el conjunto exacto de registros que estamos buscando cuando se ejecuta la aplicación. La advertencia desaparece si cambio el signo = a IS. Pero, ¿por qué apareció esta advertencia en un proyecto y no en otros? Es confuso cuando incluso en MSDN hay ejemplos que usan el operador de iguales.

+0

VB.NET LINQ también tiene la palabra clave 'Equals'. No tengo forma de probarlo, pero tal vez intente eso en su lugar? 'Donde a.MyField Equals Nothing' –

+0

@Cory: es una palabra clave contextual que solo se usa en las cláusulas' Join' (AFAIK). No creo que puedas usarlo en ningún otro lado. –

Respuesta

2

Creo que lo que está viendo aquí es que MyField es un tipo Nullable(Of T). Probablemente una primitiva Integer, Single, etc ...

La razón por la que se está viendo esta advertencia se debe a que el compilador promueve el operador de igualdad normal para el tipo primitivo de la versión Nullable(Of T). En esencia, se ejecuta el siguiente

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

La cuestión es sin embargo que cuando Integer? tiene el valor Nothing no comparará igual a nada. Por lo tanto, la cláusula Where anterior siempre devolverá False. El compilador intenta advertirle sobre esta esquina problemática de Nullable(Of T) y lo empuja a una comprobación Is Nothing que determinará si a.MyField tiene un valor no nulo.

Este artículo de blog tiene una explicación muy detallada de por qué se genera esta advertencia y todos los mecanismos detrás de ella. El artículo está escrito para C#, pero la premisa básica también se aplica a VB.Net.

+0

Entonces, si entiendo este derecho, el signo igual funcionó en una consulta porque el campo no era nulable pero era un problema en otra consulta porque es anulable, por lo tanto requiere una sintaxis diferente. –

+0

@ChrisJones correcto. Normalmente puede usar '=' con un valor que admite valores NULL. Sin embargo, la comparación con 'Nothing' siempre devolverá' False', por lo que el compilador emite una advertencia al respecto – JaredPar

+0

Jugando con esto un poco más, puedo hacer = Nothing para enrutar campos que son anulables en la base de datos, pero no los demás datos tipos y puede usar Is Nothing o el miembro HasValue que mencionó Afshin. Gracias por arrojar algo de luz sobre esto. –

5

columna generada debe ser un Nullable(Of T)

para que pueda comprobar si ese campo tiene valor o no de esta manera:

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

Intenté esto en varios tipos de datos y no funcionaría en valores de cadena. Pude utilizar el miembro HasValue en enteros nulables, fechas y tipos de datos booleanos. –

0

Al menos en LINQ a objetos puede usar esto en su lugar:

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

Esto funciona bien con ambos, ninguno o ninguno de los dos valores es Nada.

Cuestiones relacionadas