#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, не знает, как его перевести (что в точности соответствует сообщению об ошибке)