Использование моего собственного метода с LINQ to Entities

У меня есть проект с LINQ, и я хочу использовать в нем свой собственный метод. Этот метод NoWhiteSpaces должен возвращать верхнюю строку без пробелов.

public static class LittleExtensions
{
    public static string NoWhiteSpaces(this String s)
    {
        return Regex.Replace(s, @"\s", string.Empty).ToUpper();
    }
}

Когда я хочу использовать этот метод с LINQ, например:

static void GetHaendler()
    {
        using (var riaService = new gkmRia())
        {
            var hladany = "someone";
            var haendlers = from hndlr in riaService.GetGkmHaendlerOutlet()
                            where hndlr.NameOutlet.NoWhiteSpaces() == hladany.NoWhiteSpaces()
                            select hndlr;
            Console.Write(haendlers.First().NameOutlet);
        }
    }

Я получаю это сообщение об ошибке:

LINQ to Entities не распознает метод 'System.String NoWhiteSpaces (System.String)', и этот метод не может быть переведен в выражение хранилища.

Любое решение? Спасибо за ваше время.

Ответы

Ответ 1

Невозможно использовать пользовательские методы или свойства с LINQ to Entities, так как LINQ to Entities должен иметь возможность преобразовать выражение в оператор SQL, который он не может сделать с вашим методом.

Способ обойти - обходить LINQ to Entities и вместо этого использовать LINQ to Objects с помощью Enumerable вместо Queryable (обратите внимание на AsEnumerable() в приведенном ниже коде):

static void GetHaendler()
{
    using (var riaService = new gkmRia())
    {
        var hladany = "someone";
        var haendlers = from hndlr in riaService.GetGkmHaendlerOutlet().AsEnumerable()
                        where hndlr.NameOutlet.NoWhiteSpaces() == hladany.NoWhiteSpaces()
                        select hndlr;
        Console.Write(haendlers.First().NameOutlet);
    }
}

Обратите внимание, что это приводит к тому, что запрос выполняется в вашем приложении, а не в базе данных, поэтому могут возникнуть некоторые последствия для производительности. Если возможно, может быть предпочтительнее изменить запрос, чтобы его можно было выразить с помощью методов поддерживаемых платформой Entity Framework.

Альтернативное выражение, поддерживаемое LINQ to Entities, может быть следующим:

var hladany = "someone".NoWhiteSpaces();
var haenflers = from hndlr in riaService.GetGkmHaendlerOutlet().
                where hndlr.NameOutlet.Replace(" ", "").Replace("\t", "") == hladany
                select hndlr;

В этом примере обрабатываются только пробелы и вкладки (регулярное выражение также обрабатывает разные пробельные символы), но я не знаю ваших точных требований, чтобы их было достаточно. Вы всегда можете подключить больше вызовов Replace для выполнения дополнительных заметок.

Ответ 2

LINQ to Entities пытается перевести каждый вызываемый метод в часть выполняемого запроса к базе данных. Когда вы пытаетесь перевести свой метод, он терпит неудачу, потому что он не знает, как представить его в SQL.

Вы можете обойти его с помощью

  • Выполнение запроса и фильтрация после материализации результатов (плохая идея, хотя если вы работаете с большими наборами данных) или
  • Использовать только поддерживаемые методы (лучший подход ИМО). Вы можете найти список поддерживаемых методов здесь:
    Метод CLR для канонического отображения функций
    Когда поддерживаются методы String.Replace() и String.ToUpper(), вам будет легко заменить свой собственный метод.