如何强制EF Core将LINQ的.Contains()转换为EF.Functions.Like()?

时间:2019-09-13 09:48:27

标签: c# entity-framework linq ef-core-3.0

我在ASP.NET Core项目中使用Syncfusion的Grid组件。在对网格视图进行排序,过滤和分页时,它将对我的IQueryable数据源执行LINQ操作。

搜索文本字段时,它使用.Contains(string)方法,该方法无法转换为SQL查询,并且会在本地进行评估。

是否可以强制EF Core更改LINQ查询(或由我自己执行)以使用.EF.Functions.Like(列,字符串)代替,因为它可以转换为SQL?

finished

1 个答案:

答案 0 :(得分:1)

您可以在执行之前修改ExpressionTree并将"".Contains()调用替换为EF.Functions.Like("", "")

public static class LinqExtensions
{
    public static IQueryable<T> FixQuery<T>(this IQueryable<T> query)
    {
        return query.Provider.CreateQuery<T>(
            new FixQueryVisitor().Visit(query.Expression)
        );
    }

    class FixQueryVisitor : ExpressionVisitor
    {
        private readonly MethodInfo _likeMethod = ExtractMethod(() => EF.Functions.Like(string.Empty, string.Empty)); 

        private static MethodInfo ExtractMethod(Expression<Action> expr)
        {
            MethodCallExpression body = (MethodCallExpression)expr.Body;

            return body.Method;
        }

        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Method.DeclaringType == typeof(string) && node.Method.Name == "Contains")
            {
                return Expression.Call(this._likeMethod, Expression.Constant(EF.Functions), node.Object, node.Arguments[0]);
            }

            return base.VisitMethodCall(node);
        }
    }
}

[...]
dataSource = dataSource.FixQuery();