c# - 带有 Linq 表达式的 EF Core SQL 函数 LIKE 方法不适用于非字符串类型

标签 c# entity-framework-core expression-trees ef-core-2.1

我能够使用如下所示的 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 的表达式

Argument Exeption: argument exception in Expression of System.Int32 can not be used for parameter for type System.String of method 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 核心版本:(ASP.NET 核心 2.1) 数据库提供者:(例如 Microsoft.EntityFrameworkCore.SqlServer) 操作系统: IDE:(例如 Visual Studio 2017 15.4)

最佳答案

“双重转换”(string)(object)e.IntCol 是一种欺骗 C# 编译器将 int 参数“传递”给期望 string 参数(如 EF.Functions.Like)。当然,如果实际调用了该方法,您将在运行时得到无效的强制转换异常。

但这个技巧有效,因为这样的方法永远不会被“调用”,而是被转换为 SQL,并且 SqlServer EF Core 提供程序删除了此类转换并允许您使用 SqlServer 隐式数据转换。我在 How can a JSON_VALUE be converted to a DateTime with EF Core 2.2? 中使用相同的技术(尽管方向相反)和 Expression tree to SQL with EF Core .

这是如何映射到 Expression 方法的。给定 Expression searchKeyExpression(具体的 Expression 类型无关紧要),重要的是 Expression.Type< 返回的 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);

关于c# - 带有 Linq 表达式的 EF Core SQL 函数 LIKE 方法不适用于非字符串类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56715091/

相关文章:

c# - 设置 ironpython : Module not found

c# - 在 EF Core 中应用所有 IEntityTypeConfiguration 派生类

c# - "The binary operator Add is not defined for the types ' System.String ' and ' System.String '."-- 真的吗?

c# - 将对象转换为 int 在 C# 中抛出 InvalidCastException

c# - 如何从配置文件重构高度重复的阅读部分

c# - 如何正确地将结构指针从 C# 传递到 C DLL

asp.net-core - 同时读取和保存到数据库的问题

c# - 如何将动态实体设置为 dbcontext Entity Framework Core?

c# - 替换 lambda 表达式中的参数

python - 有没有办法以编程方式生成 Python 字节码?