ССЫЛКА на SQL: IQueryable — string contains — метод не имеет поддерживаемого перевода в SQL

#linq-to-sql

#linq-to-sql

Вопрос:

Уважаемые эксперты LINQ или linq2sql, можете ли вы помочь мне решить этот случай?

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

 string searchAuthor = "foo";
IQUeryable books = BookStaticRepository.SelectAll();

books.Where(r => r.Authors.Any(x => searchAuthor.Contains(x.lastname, StringComparison.OrdinalIgnoreCase)));
  

Что я получаю от этой ошибки:

Метод ‘Boolean Содержит(System.Строка, система.Строка, система.StringComparison)’ не имеет поддерживаемого перевода в SQL.

Я уже пробовал то же самое, но с использованием IEnumerable, и это сработало. Мне пришлось переключиться на IQueryable из-за проблем с производительностью… Мне это нужно для работы с IQueryable.

Спасибо за вашу помощь.

Комментарии:

1. Если вы не изменили параметры сортировки на сервере, TSQL выполняет поиск без учета регистра, поэтому вам не нужна перегрузка содержимого.

2. вы правы, «StringComparison. » OrdinalIgnoreCase» не требовалось, поскольку я создавал запрос к БД, а не к IEnumerable, но даже при удалении этого у меня было то же сообщение об ошибке, что не было поддерживаемого перевода в SQL…

Ответ №1:

Эта конкретная перегрузка Contains не работает, но игнорирование StringComparison приведет к переводу в SQL, который сгенерирует LIKE %SearchInput% . По умолчанию это будет без учета регистра, если только ваша база данных не настроена на учет регистра.

Вот так:

 string searchAuthor = "foo";
IQUeryable books = BookStaticRepository.SelectAll();

books.Where(r => r.Authors.Any(x => searchAuthor.Contains(x.lastname)));
  

Ответ №2:

Привет, ребята, спасибо, я сам нашел решение:

 books.Where(r => r.Authors.Any(x => x.lastname.Contains(searchAuthor)));
  

Ошибка — я думаю — заключалась в том, что я выполнял своего рода «противоположную работу»: я говорил, что «фамилия должна содержать строку searchAuthor», а не наоборот (фамилия должна содержать строку SearchAuthor… который теперь дает мне результаты, которые я ожидаю).

Забавно, что точно такой же запрос, который я опубликовал в своем первоначальном вопросе, отлично работал с использованием IEnumerable.

Комментарии:

1. Что ж, MiG дал вам правильный ответ выше — вероятно, это должен быть принятый ответ.

2. Привет, Фрэнк, не совсем, я уже тестировал этот способ, прежде чем запрашивать stackoverflow, и я получил ошибку (с и без StringComparison). Я просто проверил это еще раз, чтобы убедиться. Посмотрите, в чем разница, кстати (x => Searchchauthor. Содержит(x.lastname)) -не работает: ошибка «Для строки поддерживаются только аргументы, которые могут быть оценены на клиенте. Содержит метод.»- и (x => x.lastname. Содержит(searchchauthor)) -работает-.

3. @firepol — А, понятно… Я пропустил, что параметры contains были неправильными.

4. Ожидается, что он работает как IEnumerable, а не как IQueryable. IEnumerable выполняется в памяти. Могут использоваться все методы, известные вашей программе. IQueryable выполняется на стороне базы данных, там могут выполняться только довольно простые стандартные функции. База данных не знает класс StringComparison, а ваш переводчик linq-to-sql, который используется при перечислении IQueryable, не знает, как его перевести (что в точности соответствует сообщению об ошибке)