2010-01-19 15 views
20

Me encontré con un problema bastante extraño con linq-to-sql. En el siguiente ejemplo,Linq donde columna == (referencia nula) no es lo mismo que columna == nulo

var survey = (from s in dbContext.crmc_Surveys 
            where (s.crmc_Retail_Trade_Id == tradeId) && (s.State_.Equals(state)) 
            select s).First(); 

Si TradeID es nulo, no se comporta como si hubiera especificado nula específicamente como esta vez,

var survey = (from s in dbContext.crmc_Surveys 
            where (s.crmc_Retail_Trade_Id == null) && (s.State_.Equals(state)) 
            select s).First(); 

Cuál es mi comportamiento deseado. De hecho, no devuelve nada a menos que ambos valores sean no nulos. No puedo entender cómo lograr esto sin varias consultas de linq diferentes. ¿Algunas ideas?

Respuesta

26

Cambio where (s.crmc_Retail_Trade_Id == tradeId) a

where (s.crmc_Retail_Trade_Id == tradeId || 
     (tradeId == null && s.crmc_Retail_Trade_Id == null)) 

Editar - basado en this post por Brant Lamborn, parece que el siguiente sería hacer lo que quiera:

where (object.Equals(s.crmc_Retail_Trade_Id, tradeId)) 

Los Null Semantics (LINQ to SQL) MSDN página enlaza a algunas interesantes info:

LIN Q a SQL no impone C# nulo o Visual Basic nada comparado semántica en SQL. Los operadores de comparación se traducen sintácticamente a sus equivalentes SQL. La semántica refleja la semántica de SQL según lo definido por el servidor o la configuración de conexión . Dos valores nulos se consideran desiguales por defecto Configuración del Servidor SQL (aunque puede cambiar la configuración para cambiar la semántica ). De todos modos, LINQ to SQL no considera la configuración del servidor en traducción de consultas.

Una comparación con el nula literal (nada) se traduce a la versión de SQL adecuado (es cero o se no nulo).

El valor de null (nada) en la colación está definido por SQL Server; LINQ to SQL no cambia la intercalación .

+1

Sí, supongo que esa es la respuesta obvia. Pero las mentes inquisitivas quieren saber por qué un nulo constante es diferente de una variable que apunta a nulo. – Boog

+0

Sospecho que Joel Coehoorn tiene razón en que el segundo caso de su pregunta se traduce a una consulta SQL que especifica nulo directamente. – jball

+0

Parece una falla muy grande o incluso un error en el analizador de linq de Microsoft para no manejar apropiadamente las referencias a objetos nulos, pero tomaré sus palabras para ello. – Boog

2

No estoy seguro de esto, pero sospecho que cuando linq-to-sql traduce eso en una cadena de consulta sql obtienes una expresión ligeramente diferente que especifica null directamente que en algún momento terminas comparando NULL consigo mismo, y NULL = NULL se define como falso.

+1

A menos que ANSI_NULLS esté desactivado. Pero eso hace que el universo implosione. – womp

1

No estoy familiarizado con LINQ, sin embargo, en general:

NULL representa un valor que falta, es desconocido o no definida. Estrictamente hablando, una variable no puede ser igual a NULL; los lenguajes de bajo nivel que proporcionan esta construcción generalmente lo hacen por conveniencia porque no hay una alternativa fácil: en un nivel más alto, generalmente es mejor confiar en ISNULL, defined, o en cualquier otra característica de su idioma.

Una variable indefinida no es igual a otra variable indefinida (y lo mismo se aplica a NULL == NULL). Joe Celko tiene un buen ejemplo de cómo escribir una consulta para encontrar a todas las personas cuyo color de cabello coincide con el color del vehículo que manejan.¿Debería esta consulta coincidir con un hombre calvo que camina por todas partes?

+1

Creo que es bastante defendible que el color de cabello inexistente de un hombre se considere compatible con la pintura de su auto no existente. – jball

+0

En idiomas de nivel bajo o alto, null es el valor hexadecimal 0x0 y null == null es verdadero. Ahora sé que esto no es cierto en SQL pero C# no es SQL, esperamos que esto se mantenga. Se supone que Linq-to-Sql es una abstracción para los usuarios de C#. Si me preguntas que MS jodió al perro, ¿me equivoco? – Boog

+0

De hecho. Estaba tratando de explicarle a la mente inquisitiva que quería saber por qué un nulo constante era diferente de una variable que apunta a uno. En la mayoría de los casos, nulo es equivalente a 0x0, un problema grave si alguna vez necesitaras un puntero al comienzo de un segmento de memoria (afortunadamente eso ya no es un problema). Digo equivalente porque creo que hay una diferencia sutil de igual. Es como decir que 1.999999999 ... no es igual a 2, es solo un inconveniente matemático que tengan el mismo valor. – Duncan

2

Otra opción para resolver esto, ya que encontré este problema también.

where (tradeId == null ? s.crmc_Retail_Trade_Id == null : s.crmc_Retail_Trade_Id == tradeId) 
Cuestiones relacionadas