为什么我的表达式树不能识别我的自定义方法?

bsa*_*egh 0 c# linq entity-framework expression-trees

我最近发布了一个关于如何编写自定义表达式树的问题(虽然我没有意识到那是我当时要求的).现在我试图使用Scott Chamberlain提供的答案来创建另一种通用方法.

我正在使用Entity Framework并且有几个实体可以通过"Name"属性进行过滤.它并不总是名为Name,但基本上就是它.

实际的过滤方法比简单的包含或开始更复杂.它更像是一个Starts With,然后将包含搜索文本的名称的任何记录追加到列表的末尾.

由于有太多实体需要执行此过滤器,我希望能够创建一个将该过滤器应用于预编译查询的扩展方法.

我想能打电话

    someQuery.ContainsName(x => x.Name, filter.Name);
Run Code Online (Sandbox Code Playgroud)

我有一个看起来像这样的扩展方法

      public static IQueryable<T> ContainsName<T>(this IQueryable<T> query, Expression<Func<T, string>> selector, string matchingName)
    {
        var name = Expression.Constant(matchingName);

        var selectorBody = selector.Body;
        var propertyName = (selectorBody as MemberExpression).Member.Name;
        var propExpression = Expression.Parameter(typeof(string), propertyName);

        var selectorParameters = selector.Parameters;

        Expression check = Expression.Call(typeof(GenericNameFilter).GetMethod("IsMatch"), propExpression, name);

        var lambada = Expression.Lambda<Func<T, bool>>(check, selectorParameters);

        return query.Where(lambada) 
    }
Run Code Online (Sandbox Code Playgroud)

IsMatch只接受2个字符串并返回一个bool.这不是该方法的最终游戏,但我希望能够让IsMatch的简单版本正常工作,然后我会扩展它.

当我在结果上调用ToList时,我得到一个例外.

"LINQ to Entities无法识别方法'Boolean IsMatch(System.String,System.String)'方法,并且此方法无法转换为商店表达式."

从我所做的搜索中我相信我想要做的事情是可能的,我只是做错了.这是我设置表达式树的方式吗?是IsMatch方法吗?一切都是错的吗?

Jon*_*Jon 5

问题的关键在于您无法编写导致代码运行的查询操作,因为数据库显然无法在其数据上运行C#代码.

您的扩展方法向查询管道添加lambda调用; 你打算将它解决为IsMatch方法的一些重载.但是,这对数据库没有任何意义,因此EF查询提供程序会告诉您它无法转换您写入SQL的内容.不幸的是,没有办法解决这个问题.

相同的代码在LINQ to对象上运行得很好,因为在那种情况下编译器当然可以安排调用你的方法.