Как реализовать функцию поиска с помощью Entity Framework? - PullRequest
6 голосов
/ 10 августа 2011

У меня есть приложение для блога , которое моделирует базу данных с использованием Entity Framework.Проблема с этим блогом в том, что стало трудно найти то, что я ищу.Для этого требуется функция поиска, но я не уверен, как реализовать это с помощью SQL и / или LINQ to Entities.

Сейчас я ищу в своей базе данных этот запрос LINQ, но, похоже, это должно быть лучше.

    public IEnumerable<BlogPost> SearchBlogPosts(string query, int page, int itemsPerPage)
    {
        var result = _dataContext.BlogPosts
            .Where(BlogPostContains(query))
            .OrderByDescending(x => x.PostedDate)
            .Skip((page - 1) * itemsPerPage)
            .Take(itemsPerPage),
        return result;
    }

    private Func<BlogPost, bool> BlogPostContains(string query)
    {
        return x => x.Title.Contains(query) || x.Body.Contains(query) || x.Author.Contains(query);
    }

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

Вопрос 1) Есть ли лучший способ выполнить поиск с помощью LINQ to Entities?

Вопрос 2) Как насчет простого SQL?Как мне написать хранимую процедуру поиска в SQL Server, чтобы я мог отобразить и использовать ее в EF вместо LINQ?

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

Заранее спасибо.

Ответы [ 4 ]

5 голосов
/ 10 августа 2011

Стандартным подходом для этого будет полнотекстовый поиск SQL. Вам нужно будет включить полный текст в БД, назначить столбцы для индексирования по полному тексту, после чего вы сможете использовать SQL Содержит запросов с использованием этих столбцов.

В настоящее время Linq to Entities не поддерживает полнотекстовые поисковые запросы - для этого вам придется прибегнуть к стандартным SQL-запросам. Вы можете использовать ExecuteStoreQuery(), чтобы по крайней мере отобразить результаты поиска в напечатанный результат.

3 голосов
/ 10 августа 2011

Параметры сортировки по умолчанию для SQL Server не чувствительны к регистру, что означает, что предложение where, подобное этому (то, что LINQ to Entities создаст из Contains) ...

where Name like '%JOHN%'

..должен найти "Джона Уэйна".Я считаю, что ваш запрос выполняется не на сервере, а на самом деле с LINQ to Objects в памяти - и там поиск чувствителен к регистру.Это LINQ to Objects, потому что вы не возвращаете Expression из вашего BlogPostContains.Подпись должна быть:

private Expression<Func<BlogPost, bool>> BlogPostContains(string query)

Если вы только возвращаете Func<BlogPost, bool>, вы работаете с перегрузкой IEnumerable (а не IQueryable) метода расширения Where, который, в свою очередь, вызываетвся таблица BlogPosts загружается первой в память.Затем фильтр применяется в памяти с LINQ to Objects.

Было бы интересно узнать, исчезает ли чувствительность к регистру, если вы вернете Expression.

(просто как примечание о вашемПроблема чувствительности к регистру, а не решение вашего общего вопроса о наилучшем способе реализации функции поиска.)

0 голосов
/ 24 февраля 2012

В соответствии с вашими поисками с использованием LINQ, вы можете попробовать что-то вроде этого, и оно прекрасно работает:

(x.Title).ToUpper().Contains(query.ToUpper())

Или аналогичного метода ToLower () также должно быть достаточно.

Для баз данных, которые действительно рассматривают прописные буквы «А», отличные от строчных букв «а», в качестве различных значений, которыми они технически являются, приведенная выше процедура LINQ даст вам результаты.

Надеюсьэто помогает.

0 голосов
/ 10 августа 2011

Я бы посмотрел на Lucene.Net для хорошего поставщика поиска.

...