2010-01-19 3 views
20

Я столкнулся с довольно странной проблемой с linq-to-sql. В следующем примереLinq где column == (нулевая ссылка) не совпадает с столбцом == null

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

Если tradeId имеет нулевое значение, это не ведет себя так, как будто я указан нулевой конкретно, как это вместо того,

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

это мое желаемое поведение. На самом деле он ничего не возвращает, если оба значения не равны нулю. Я не могу понять, как выполнить это несколько различных запросов linq. Есть идеи?

ответ

26

Изменение where (s.crmc_Retail_Trade_Id == tradeId) в

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

Edit - на основе this post по Брант Lamborn, он выглядит следующим образом будет делать то, что вы хотите:

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

The Null Semantics (LINQ to SQL) MSDN страница ссылается на некоторые интересные info:

LINQ to SQL не налагает C# null или Visual Basic ничего не сравнивает семантика на SQL. Операторы сравнения синтаксически переведены в их эквиваленты SQL . Семантика отражает SQL-семантику, определенную сервером, или параметры подключения. Два нулевых значения считаются неравными по умолчанию Параметры SQL Server (хотя вы можете изменить настройки для изменения семантики ). Несмотря на это, LINQ to SQL не учитывает настройки сервера в переводе запросов .

Сравнение с буквальным нулевой (ничего) переводится на соответствующей версии SQL (равно нулю или не равно нулю).

Значение null (ничего) в сопоставление определяется SQL Server; LINQ to SQL не изменяет сопоставление .

+1

Да, я полагаю, это очевидный ответ. Но вопрошающие умы хотят знать, почему константа null отличается от переменной, указывающей на null. – Boog

+0

Я подозреваю, что Джоэл Коэхорн прав, что второй случай в вашем вопросе переводится в SQL-запрос, задающий нуль напрямую. – jball

+0

Это похоже на очень большой недостаток или даже ошибку в синтаксисе linq от Microsoft, чтобы не обрабатывать ссылки на нулевые объекты, но я возьму ваши слова за это. – Boog

2

Не уверен в этом, но я подозреваю, что когда linq-to-sql переводит это в строку запроса sql, вы получаете немного другое выражение, определяющее null, так, чтобы в какой-то момент вы закончили сравнение NULL с самим собой и NULL = NULL определяется как false.

+1

Если ANSI_NULLS не установлен в положение OFF. Но это заставляет вселенную взорваться. – womp

1

Я не знаком с Linq, однако в целом:

NULL представляет собой недостающее, неизвестное или неопределенное значение. Строго говоря, переменная не может равняться NULL; низкоуровневые языки, которые обеспечивают эту конструкцию, обычно делают это как удобство, потому что нет простой альтернативы - на более высоком уровне обычно лучше полагаться на ISNULL, defined или на любые другие функции, предлагаемые на вашем языке.

Одна неопределенная переменная не равна другой неопределенной переменной (и то же самое относится к NULL == NULL). Joe Celko имеет хороший пример написания запроса, чтобы найти всех людей, цвет волос которых соответствует цвету автомобиля, которым они управляют.Должен ли этот запрос соответствовать лысому человеку, который ходит везде?

+1

Я думаю, что довольно оправданно, что цвет несуществующих волос человека считается совпадением с краской несуществующего автомобиля. – jball

+0

На языках низкого или высокого уровня значение null равно шестнадцатеричному значению 0x0, а null == null - true. Теперь я знаю, что это неверно в SQL, но C# не является SQL, мы ожидаем, что это задержит. Предполагается, что Linq-to-Sql является абстракцией для пользователей C#. Если вы спросите меня, что MS привинчило pooch, я ошибаюсь? – Boog

+0

Действительно. Я больше пытаюсь объяснить интересующемуся разуму, который хотел бы знать, почему постоянный нуль отличается от переменной, указывающей на один. В большинстве случаев нуль эквивалентен 0x0, серьезная проблема, если вам когда-либо понадобился указатель на начало сегмента памяти (к счастью, это уже не проблема). Я говорю эквивалент, потому что я думаю, что есть незначительное отличие от равного. Это как сказать, что 1.999999999 ... не равно 2, это всего лишь математическое неудобство, что они оказываются одинаковыми. – Duncan

2

Еще одна возможность решить эту проблему, так как я столкнулся с этой проблемой.

where (tradeId == null ? s.crmc_Retail_Trade_Id == null : s.crmc_Retail_Trade_Id == tradeId) 
Смежные вопросы