Как использовать SQL 'LIKE' с LINQ to Entities? - PullRequest
29 голосов
/ 22 июня 2010

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

Joh*
*Johnson
*mit*
*ack*on

Перед использованием LINQ to Entities у меня была хранимая процедура, которая принимала эту строку в качестве параметраи сделал:

SELECT * FROM Table WHERE Name LIKE @searchTerm

А потом я просто сделал бы String.Replace ('*', '%'), прежде чем передать его.

Теперь с LINQ to Entities я пытаюсьсделать то же самое.Я знаю, что есть поддержка StartsWith, EndsWith и Contains, но она не будет поддерживать ее так, как мне нужно.

Я читал о "SqlMethods.Like" и пробовал это:1013 * Однако я получаю следующее исключение:

LINQ to Entities does not recognize the method 'Boolean Like(System.String, 
System.String)' method, and this method cannot be translated into a store 
expression.

Как бы я получил такую ​​же функциональность, используя LINQ to Entities?

Ответы [ 11 ]

34 голосов
/ 22 июня 2010

http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/6529a35b-6629-44fb-8ea4-3a44d232d6b9/

var people = entities.People.Where("it.Name LIKE @searchTerm", new ObjectParameter("searchTerm", searchTerm));
12 голосов
/ 05 июля 2012

Как заставить его работать без проблем:

в вашей модели EDMX, добавьте:

    <Function Name="String_Like" ReturnType="Edm.Boolean">
      <Parameter Name="searchingIn" Type="Edm.String" />
      <Parameter Name="lookingFor" Type="Edm.String" />
      <DefiningExpression>
        searchingIn LIKE lookingFor
      </DefiningExpression>
    </Function>

сразу после запуска разделов:

<edmx:ConceptualModels> <Schema Namespace="Your.Namespace"...

Затем в любом месте вашего кода добавьте этот метод расширения:

    //prior to EF 6 [System.Data.Objects.DataClasses.EdmFunction("Your.Namespace", "String_Like")]

    //With EF 6
    [System.Data.Entity.DbFunction("Your.Namespace", "String_Like")]
    public static bool Like(this string input, string pattern)
    {
        /* Turn "off" all regular expression related syntax in
         * the pattern string. */
        pattern = Regex.Escape(pattern);

        /* Replace the SQL LIKE wildcard metacharacters with the
         * equivalent regular expression metacharacters. */
        pattern = pattern.Replace("%", ".*?").Replace("_", ".");

        /* The previous call to Regex.Escape actually turned off
         * too many metacharacters, i.e. those which are recognized by
         * both the regular expression engine and the SQL LIKE
         * statement ([...] and [^...]). Those metacharacters have
         * to be manually unescaped here. */
        pattern = pattern.Replace(@"\[", "[").Replace(@"\]", "]").Replace(@"\^", "^");

        return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase);
    }

И вот оно у вас.

Теперь вы можете сделать:

(from e in Entities
 where e.Name like '%dfghj%'
 select e)

или

string [] test = {"Sydney", "Melbourne", "adelaide", "ryde"};

test.Where(t=> t.Like("%yd%e%")).Dump();
8 голосов
/ 22 июня 2010

Ну, ваш выбор:

3 голосов
/ 25 марта 2012

Вы можете сделать это:

using System.Data.Entity;  // EntityFramework.dll v4.3
var queryResult=db.Accounts.AsQueryable().Where(x => x.Name.Contains(queryKey));

, поскольку Linq в Entity не может преобразовать метод Contains() в SQL, но Linq в SQL может это сделать.Я попытался найти метод, который может выполнять приведение, наконец, AsQueryable(), а также универсальную версию AsQueryable<T>().Я обнаружил, что могу сделать это, используя это таким образом в моем случае, но любой побочный эффект, который он имеет, я не знаю, возможно, он потеряет какую-то функцию в Entity.

2 голосов
/ 03 июня 2015

решение заключается в использовании SQLFunctions.PatIndex

var result = from c in items
             where SqlFunctions.PatIndex(searchstring.ToLower(), c.fieldtoSearch) > 0
             select c;

где searchstring - шаблон для поиска 'fieldtoSearch' - это поле для поиска

Patindex () поддерживает поиск с использованием поиска по строковому шаблону. Поиск не чувствителен к регистру.

1 голос
/ 20 июля 2018

Теперь EF поддерживает использование «LIKE», и вы можете использовать все шаблоны SQL.Проверьте это.

var people = from t in entities.People
             select new { t.Name };
people = people.Where(x => DbFunctions.Like(x.Name, searchTerm));
1 голос
/ 17 января 2015

Вы можете сделать все эти заявления с LINQ, как это

string _search = "johnson";
// joh* OR joh%
items.Where(i => i.Name.StartsWith(_search, StringComparison.OrdinalIgnoreCase));
// *son OR %son
items.Where(i => i.Name.EndsWith(_search, StringComparison.OrdinalIgnoreCase));
// *hns* OR %hns%
items.Where(i => i.Name.ToLower().Contains(_search));
1 голос
/ 22 июня 2010
var people = from t in entities.People
                 where t.Name.ToLower().Contains(searchTerm.ToLower())
                 select new { t.Name };

РЕДАКТИРОВАТЬ - Я мог бы смешивать синтаксис. Я обычно использую методы расширения; но содержит будет работать.

0 голосов
/ 20 августа 2018

Это легко достигается с помощью следующих методов

var people = from t in entities.People
             where t.Name.Contains(searchTerm)
             select new { t.Name };

Используйте следующие спецификации для подстановочных знаков

LIKE 'a%' => StartsWith("a")
LIKE '%a' => EndsWith("a")
LIKE '%a%' => Contains("a")
LIKE 'a%b' => StartsWith("a") && EndsWith("b")
LIKE '%a%b%' => StartsWith("a") && Contains("b")
0 голосов
/ 30 января 2017

Мы используем Database First и EntityFramework.

«Сопоставьте свою собственную функцию».подход работает для нас вместе с nuget EntityFramework.CodeFirstStoreFunctions .

1 Шаг: создайте функцию в БД следующим образом:

CREATE FUNCTION [dbo].[StringLike]
(
      @a nvarchar(4000),
      @b nvarchar(4000)
)
RETURNS bit
AS
BEGIN
    RETURN 
    (SELECT CASE
            WHEN (SELECT 1 WHERE @a LIKE @b) = 1 THEN 1
            ELSE 0
            END)  
END

2 Шаг: установите nugetEntityFramework.CodeFirstStoreFunctions

3 Шаг: Создайте метод в своем коде, как этот (я создаю мой в классе DbContext):

[DbFunction("CodeFirstDatabaseSchema", "StringLike")]
public static bool Like(string input, string pattern)
{
    throw new NotSupportedException("Direct calls are not supported.");
}

4 Шаг: Инициализируйте EntityFramework.CodeFirstStoreFunctions.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Add(new FunctionsConvention("dbo", this.GetType()));
}

5 Шаг: теперь вы можете использовать этот метод в своем запросе linq.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...