Linq SqlMethods. Как сбои

Я следую советам здесь, пытаясь усилить оператор, что sql не становится созданным, пока перечислитель не смещен. Однако я получаю следующую ошибку на коде ниже. Я использую Linq2Entities, не linq2sql. Существует ли способ сделать это в Linq2entities?

Метод 'булевская переменная Как (Система. Строка, Система. Строка)', не может использоваться на клиенте; это только для перевода в SQL.

            query = db.MyTables.Where(x => astringvar.Contains(x.Field1));

            if (!String.IsNullOrEmpty(typeFilter))
            {
                if (typeFilter.Contains('*'))
                {
                    typeFilter = typeFilter.Replace('*', '%');
                    query = query.Where(x=> SqlMethods.Like(x.Type, typeFilter));
                }
                else
                {
                    query  = query.Where(x => x.Type == typeFilter);
                }
            }

Примечания: дб является объектом, отображающимся на SQL-сервер.

7
задан Russell Steen 6 April 2010 в 12:48
поделиться

3 ответа

Я не знаю, как можно заставить Entity Framework использовать "настоящий" оператор LIKE, но возможным обходным путем было бы выразить выражение LIKE в терминах of StartsWith , Contains and EndsWith

Например:

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")

И так далее ...

Обратите внимание, что это не совсем эквивалентно использованию LIKE в SQL: например, LIKE '% abc% bcd%' приведет к Contains ("abc") && Contains ("bcd") . Это будет соответствовать "abcd", даже если исходное условие LIKE не совпадет. Но в большинстве случаев этого должно быть достаточно.

Вот пример реализации с использованием PredicateBuilder и LinqKit для построения выражений на основе шаблона LIKE:

public static class ExpressionHelper
{
    public static Expression<Func<T, bool>> StringLike<T>(Expression<Func<T, string>> selector, string pattern)
    {
        var predicate = PredicateBuilder.True<T>();
        var parts = pattern.Split('%');
        if (parts.Length == 1) // not '%' sign
        {
            predicate = predicate.And(s => selector.Compile()(s) == pattern);
        }
        else
        {
            for (int i = 0; i < parts.Length; i++)
            {
                string p = parts[i];
                if (p.Length > 0)
                {
                    if (i == 0)
                    {
                        predicate = predicate.And(s => selector.Compile()(s).StartsWith(p));
                    }
                    else if (i == parts.Length - 1)
                    {
                        predicate = predicate.And(s => selector.Compile()(s).EndsWith(p));
                    }
                    else
                    {
                        predicate = predicate.And(s => selector.Compile()(s).Contains(p));
                    }
                }
            }
        }
        return predicate;
    }
}

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

var expr = ExpressionHelper.StringLike<YourClass>(x => x.Type, typeFilter);
query = query.AsExpandable().Where(expr.Compile());

Я только что попробовал это с простой моделью EF, и, похоже, она работает нормально :)

11
ответ дан 6 December 2019 в 09:59
поделиться

Класс SqlMethods предназначен для использования с LINQ-to-SQL. Когда вы используете из него методы (которые в общедоступной документации не рекомендуется делать, это не для общего пользования), поставщик IQueryable для LINQ-to-Entities не знает, что с ним делать и как перевести это.

Если у вас есть один подстановочный знак в начале или конце фильтра, вы можете использовать методы StartsWith или EndsWith в классе String и LINQ-to-Entities будет поддерживать это.

Однако в этом случае у вас есть переменное количество подстановочных знаков, поэтому вам придется спуститься до уровня ESQL и построить запрос на его основе, как указано в ответе Nix .

4
ответ дан 6 December 2019 в 09:59
поделиться

Вы можете выполнить ESQL и сделать что-то вроде следующего ..

     db.MyTables.Where("it.Type like '" + typeFilter + "'").ToList();
4
ответ дан 6 December 2019 в 09:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: