如何在C#中创建适配Entity Framework的自定义Like Expression
实现方案
核心说明
.NET 原生表达式树没有内置Like二元运算符,所以无法直接返回标准BinaryExpression实例,但我们可以构造EF可识别的方法调用表达式,完全适配你现有字典的Func<Expression, Expression, Expression>类型要求。
EF Core 版本实现
先引用必要命名空间:
using System.Linq.Expressions; using Microsoft.EntityFrameworkCore;
方法实现代码:
public static Expression Like(Expression left, Expression right) { // 反射获取EF.Functions.Like方法 var likeMethod = typeof(DbFunctionsExtensions) .GetMethod(nameof(DbFunctionsExtensions.Like), new[] { typeof(DbFunctions), left.Type, right.Type }) ?? throw new InvalidOperationException("未找到匹配的EF.Functions.Like方法"); // 构造方法调用表达式,EF查询翻译时会自动转为SQL LIKE语句 return Expression.Call( null, likeMethod, new Expression[] { Expression.Constant(EF.Functions), left, right } ); }
添加到你的表达式字典即可使用:
var expressions = new Dictionary<string, Func<Expression, Expression, Expression>> { { "is equal to", Expression.Equal }, { "greater than", Expression.GreaterThan }, { "like", Like } };
EF 6 版本实现
如果使用的是.NET Framework版本的EF 6,改用SqlFunctions.PatIndex实现:
using System.Linq.Expressions; using System.Data.Entity.SqlServer; public static Expression Like(Expression left, Expression right) { var patIndexMethod = typeof(SqlFunctions) .GetMethod(nameof(SqlFunctions.PatIndex), new[] { typeof(string), typeof(string) }) ?? throw new InvalidOperationException("未找到匹配的SqlFunctions.PatIndex方法"); // PatIndex返回匹配位置,大于0即匹配成功,等价于LIKE var patIndexCall = Expression.Call(patIndexMethod, right, left); return Expression.GreaterThan(patIndexCall, Expression.Constant(0)); }
关于返回BinaryExpression的说明
如果必须严格遵循返回BinaryExpression的签名,你需要自定义派生自BinaryExpression的自定义表达式类型,同时配合自定义表达式访问器在查询翻译前做表达式替换,常规业务场景下不需要这么做,上面的实现已经可以直接正常工作。
内容的提问来源于stack exchange,提问作者barteloma
相关产品推荐
相关产品推荐

