Entity Framework Linq имеет значение Null, это не проблема Null

У меня есть метод, который получает идентификатор категории, за которым следуют два необязательных строковых параметра, которые по умолчанию равны нулю.

Я попытался использовать несколько похожих ответов на другие вопросы о SO, но ни один из них не помог.

Я пытаюсь заставить запрос linq to EF работать следующим образом:

Если какой-либо необязательный параметр имеет значение, используйте это значение, в противном случае используйте Is Null.

Если присутствуют оба необязательных параметра, используйте их как часть запроса или любой из них, если он предоставлен. Но если параметры не добавлены, просто используйте идентификатор категории.

Оба необязательных параметра в базе данных помечены как обнуляемые.

Вот код, который не работает:

          from c in dtx.Categories
          where c.CategoryId == CatId
         && (string.IsNullOrEmpty(param1) ? c.Param1 == null : c.Param1 == param1)
         && (string.IsNullOrEmpty(param2) ? c.Param2 == null : c.Param2 == Param2)
        select c

Попробуйте два:

          from c in dtx.Categories
          where c.CategoryId == CatId
          && (c.Param1 == null ? c.Param1 == null : c.Param1 == param1)
          && (c.Param2 == null ? c.Param2 == null : c.Param2 == param2)
          select c

Ошибки не выдаются, но оба запроса всегда возвращают нулевые результаты, если не указаны оба параметра.

Один из постов, которые я пробовал: Как я могу запросить нулевые значения в структуре сущностей?


person SetiSeeker    schedule 24.05.2012    source источник
comment
Разве Param2 не должен быть param2? Это может быть просто проблема с публикацией.   -  person marteljn    schedule 24.05.2012


Ответы (4)


Насколько я могу судить, проблема выглядит так, будто условие запроса написано неправильно. Давайте проверим, что будет добавлено, на примере:

Данные:

Id = 1, Param1 = null, Param2 = null
Id = 2, Param1 = 'a'   param2 = null
Id = 3, Param1 = null, Param2 = 'b'
Id = 4, Param1 = 'a'   param2 = 'c'

С текущим запросом и другим предложенным решением вы получите только идентификатор 1. Ваше условие говорит: если Param1 имеет значение Null и c.Param1 (сохраненное значение) равно null OR c.Param1 равно значению Param1.

Вам нужно условие, которое гласит: Если Param1 Is Null ИЛИ c.Param1 равен значению Param1.

Если вы используете этот запрос, вы всегда получите свой результат.

from c in dtx.Categories
where c.CategoryId == CatId
    && (string.IsNullOrEmpty(param1) || c.Param1 == param1)
    && (string.IsNullOrEmpty(param2) || c.Param2 == param2)
select c
person Stephan    schedule 24.05.2012

3-е редактирование на удачу, может быть, на этот раз я правильно прочитал вопрос :)

var p1 = string.IsNullOrEmpty(param1) ? null : param1;
var p2 = string.IsNullOrEmpty(param2) ? null : param2;

var query = dtx.Categories.Where(c => c.CategoryId == CatId);
if (p1 != null || p2 != null) {
    query = query.Where(c => c.Param1 == p1 && c.Param2 == p2);
}
person Martin Ernst    schedule 24.05.2012
comment
Кажется, вернуть все предметы. - person SetiSeeker; 25.05.2012

вы должны явно развернуть чек, либо оба null, либо они совпадают

((string.IsNullOrEmpty(param1) && c.Param1 == null) || (c.Param1 == param1))

РЕДАКТИРОВАТЬ: только что протестировано, и не имеет значения, проверяете ли вы null или нет, SQL тот же, так что просто сделайте

from c in dtx.Categories 
    where c.CategoryId == CatId 
       && (c.Param1 == param1) 
       && (c.Param2 == Param2) 
select c 
person Kris Ivanov    schedule 24.05.2012
comment
Редактирование кажется правильным, однако оно не вернет true, если либо значение db равно '', а param равно null, либо значение db равно null, а param равно . - person Danny Varod; 24.05.2012
comment
Это была моя первоначальная попытка, и я повторил их сейчас, но я все еще получаю нулевые результаты. Спасибо за помощь. - person SetiSeeker; 24.05.2012

Проблема в том, что вы написали

from ... where c.Param1 == null ...

LINQ переводит его в то же выражение SQL:

SELECT ... FROM ... WHERE Param1 = null ...

но вам нужно это:

SELECT ... FROM ... WHERE Param1 IS NULL ...

Итак, вот правильное решение:

from c in dtx.Categories
where c.CategoryId == CatId && 
     (param1 == null ? !c.Param1.HasValue : c.Param1.Value == param1) && 
     (param2 == null ? !c.Param2.HasValue : c.Param2.Value == param2)
select c
person Aleksey Timkov    schedule 24.10.2013