Запрос Linq не ведет себя так, как ожидалось

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

var result = (from r in employeeRepo.GetAll()
              where r.EmployeeName.Contains(searchString) 
                    || r.SAMAccountName.Contains(searchString)
              orderby r.EmployeeName
              select new SelectListItem 
              { 
                  Text = r.EmployeeName, 
                  Value = r.EmployeeName 
              });

Проблема по какой-то странной причине дает мне запись каждого человека, которого я ищу, в нижнем регистре или в верхнем регистре. т.е.

  • тестовый пользователь
  • Пользователь теста
  • ИСПЫТАТЕЛЬНЫЙ ПОЛЬЗОВАТЕЛЬ

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

Каждое первое и последнее имя в базе данных начинаются с верхнего регистра.

Используется searchString, который я использую:

  • richard - Я получаю правильные результаты
  • waidande - результаты не найдены

Оба этих пользователя находятся в базе данных.

Я также использую Entity Framework для запроса Sql Server 2012.

Ответ 1

Если ваш текст имеет NVARCHAR данных NVARCHAR проверьте похожие буквы, которые на самом деле не совпадают:

CREATE TABLE #employee (ID INT IDENTITY(1,1), EmployeeName NVARCHAR(100));

INSERT INTO #employee(EmployeeName) VALUES (N'waidаnde');

SELECT *
FROM #employee
WHERE EmployeeName LIKE '%waidande%';

-- checking
SELECT *
FROM #employee
WHERE CAST(EmployeeName AS VARCHAR(100)) <> EmployeeName;

ДБ <> Fiddle Demo

Здесь: 'а' ! = 'a'. Один из Cyrillic 'a' а второй нормально.


Идея взята из:

enter image description here

Слайд с: http://sqlbits.com/Sessions/Event12/Revenge_The_SQL

PS Я настоятельно рекомендую посмотреть выступление Роба Волка: Revenge: The SQL! ,

Ответ 2

Чтобы устранить эту проблему, определите, есть ли проблема на стороне EF или на стороне БД. Общей ошибкой является лишний пробел, поэтому перед продолжением убедитесь, что это не так.

Сначала проверьте, какой запрос генерируется EF, вы можете использовать один из следующих методов для этого

Если вы правильно используете EF и ваш запрос переводится на SQL, как ожидалось, и содержит предикаты в разделе where, но вы все равно не получаете каких-либо значимых результатов, вот несколько идей, которые нужно попробовать на стороне БД:

  • Проверьте сопоставление (помните, что он может быть установлен на сервере, базе данных и отдельном уровне столбца) - будьте осторожны с чувствительностью к регистру и кодовой страницей, которая используется
  • Убедитесь, что ваша строка поиска содержит символы, которые могут быть интерпретированы на кодовой странице db - например, если кодовая страница - 252 - Windows Latin 1 ANSI, и вы отправляете ввод с символами из UTF-16, которые находятся за пределами ANSI - вы выиграли не получаю никаких результатов, даже если символы выглядят одинаково.
  • Очень маловероятно, но в качестве последнего средства проверьте, не был ли кешированный один из ваших запросов, как описано здесь

Ответ 3

SQL Server 2012 (SQL Server) устанавливается по умолчанию с учетом нечувствительности к регистру. Если вам нужно извлечь записи из базы данных с учетом чувствительности к регистру (поскольку у вас есть несколько "записей" ), вам нужно изменить сортировку (будьте осторожны, потому что, если вы изменяете сортировку СУБД, вы изменяете также сортировку базы данных базы данных, поэтому также становятся именами таблиц и полей чувствителен к регистру).
Если вам не нужно избегать получения всех записей из СУБД, вы можете просто фильтровать записи после их извлечения, т.е.

var result = (from r in employeeRepo.GetAll()
          where r.EmployeeName.Contains(searchString) 
                || r.SAMAccountName.Contains(searchString)
          orderby r.EmployeeName
          select new SelectListItem 
          { 
              Text = r.EmployeeName, 
              Value = r.EmployeeName 
          })
          .ToList()  // Materialize records and apply case sensitive filter
          .Where(r.EmployeeName.Contains(searchString) 
                || r.SAMAccountName.Contains(searchString));