EF Core SQL Функция LIKE с выражением Linq не работает для нестроковых типов - PullRequest
1 голос
/ 22 июня 2019

я могу создать выражение вызова с функциями SQL, как показано ниже

var likeMethod = typeof(DbFunctionsExtensions).GetMethod("Like", new[] { typeof(DbFunctions), typeof(string), typeof(string) });

Expression.Call(null, likeMethod, Expression.Constant(EF.Functions), searchKeyExpression, Expression.Constant($"%{filter.Value}%"));

Мне просто нужно понять, как я могу использовать эту функциональность для столбцов, таких как целые или десятичные столбцы, для использования с функциями Like.Если я использую вышеупомянутое выражение, я получаю ошибку ниже.Как я могу использовать выражение с ef, как со строковым типом данных

Аргумент Исключение: исключение аргумента в выражении System.Int32 нельзя использовать для параметра для типа System.String метода Boolean Like (Ef.DBfuntions)

Шаги для воспроизведения

var likeMethod = typeof(DbFunctionsExtensions).GetMethod("Like", new[] { typeof(DbFunctions), typeof(string), typeof(string) });

Expression.Call(null, likeMethod, Expression.Constant(EF.Functions), searchKeyExpression, Expression.Constant($"%{filter.Value}%"));

Как я вижу, есть возможность сделать это в методе Ef.Functions Like в следующем примере

context.Set<MyEntity>().Where(e => EF.Functions.Like((string)(object)e.IntCol, "%1%"))

но как я могу это сделать с помощью выражений членов.

Источник: - https://github.com/aspnet/EntityFrameworkCore/issues/9578

Это решение для запроса по прямой линии.https://github.com/aspnet/EntityFrameworkCore/issues/16195

Дополнительные технические сведения

Версия EF Core: (ASP.NET Core 2.1) Поставщик базы данных: (например, Microsoft.EntityFrameworkCore.SqlServer) Операционная система: IDE: (например, Visual Studio 201715,4) * * один тысяча двадцать шесть

1 Ответ

3 голосов
/ 22 июня 2019

«Двойное приведение» (string)(object)e.IntCol - это способ обмануть компилятор C #, чтобы «передать» аргумент int методу, ожидающему параметр string (например, EF.Functions.Like). Конечно, если метод действительно вызывается, вы получите недопустимое исключение приведения во время выполнения.

Но хитрость работает, потому что такие методы никогда не "вызываются", а переводятся в SQL, а поставщик SqlServer EF Core удаляет такие приведения и позволяет вам использовать неявные преобразования данных SqlServer. Я использую ту же технику (хотя и в противоположном направлении) в Как преобразовать JSON_VALUE в DateTime с EF Core 2.2? и Дерево выражений в SQL с EF Core .

Вот как это сопоставляется с Expression методами. Учитывая Expression searchKeyExpression (конкретный тип Expression не имеет значения), важным является Type, возвращаемый свойством Expression.Type. Если это string, у вас все в порядке, в противном случае вам нужно применить к нему (string)(object) приведений, что достигается двумя Expression.Convert вызовами.

Примерно так:

Expression matchExpression = searchKeyExpression;
if (matchExpression.Type != typeof(string))
{
    matchExpression = Expression.Convert(matchExpression, typeof(object));
    matchExpression = Expression.Convert(matchExpression, typeof(string));
}
var pattern = Expression.Constant($"%{filter.Value}%);
var callLike = Expression.Call(
    typeof(DbFunctionsExtensions), "Like", Type.EmptyTypes,
    Expression.Constant(EF.Functions), matchExpression, pattern);
...