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

C# 为什么我的表达式树不能识别我的自定义方法?,c#,linq,entity-framework,expression-trees,C#,Linq,Entity Framework,Expression Trees,我最近在上发布了一个问题(尽管我当时不知道我在问这个问题)。现在,我尝试使用Scott Chamberlain提供的答案创建另一个通用方法 我使用的是实体框架,有几个实体可以通过类似“Name”属性的内容进行过滤。它并不总是被称为名字,但它基本上就是这个名字 实际的筛选方法比简单的包含或开头更复杂。它更像是以开头,然后将包含搜索文本的名称的任何记录附加到列表的末尾 由于需要执行此过滤器的实体太多,因此我希望能够创建一个扩展方法,将该过滤器应用于预编译的查询 我想打个电话 someQuer

我最近在上发布了一个问题(尽管我当时不知道我在问这个问题)。现在,我尝试使用Scott Chamberlain提供的答案创建另一个通用方法

我使用的是实体框架,有几个实体可以通过类似“Name”属性的内容进行过滤。它并不总是被称为名字,但它基本上就是这个名字

实际的筛选方法比简单的包含或开头更复杂。它更像是以开头,然后将包含搜索文本的名称的任何记录附加到列表的末尾

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

我想打个电话

    someQuery.ContainsName(x => x.Name, filter.Name);
我有一个如下所示的扩展方法

      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) 
    }
publicstaticiQueryable容器名称(此IQueryable查询、表达式选择器、字符串匹配名称)
{
变量名称=表达式.常量(匹配名称);
var selectorBody=selector.Body;
var propertyName=(selectorBody作为MemberExpression).Member.Name;
var propExpression=Expression.Parameter(typeof(string),propertyName);
var selectorParameters=选择器参数;
表达式检查=Expression.Call(typeof(GenericNameFilter).GetMethod(“IsMatch”),propExpression,name);
var lambada=Expression.Lambda(检查、选择或参数);
返回query.Where(lambada)
}
IsMatch只接收2个字符串并返回布尔值。这并不是该方法的最终目的,但我希望能够得到一个简单版本的IsMatch,然后我会扩展它

当我对结果调用ToList时,我得到一个异常

LINQ to Entities无法识别方法“Boolean IsMatch(System.String,System.String)”方法,此方法无法转换为存储表达式


从我所做的搜索中,我相信我正在尝试做的是可能的,我只是做得不对。这是我设置表达式树的方式吗?是IsMatch方法吗?这一切都错了吗?

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

扩展方法向查询管道添加lambda调用;您希望将其解析为
IsMatch
方法的一些重载。但是,这对数据库没有任何意义,因此EF查询提供程序告诉您,它无法将您编写的内容转换为SQL。不幸的是,这是没有办法的


同样的代码可以在LINQ to对象上正常运行,因为在这种情况下,编译器当然可以安排调用您的方法。

问题的要点是,您不能编写导致代码运行的查询操作,因为数据库显然无法在其数据上运行您的C#代码

扩展方法向查询管道添加lambda调用;您希望将其解析为
IsMatch
方法的一些重载。但是,这对数据库没有任何意义,因此EF查询提供程序告诉您,它无法将您编写的内容转换为SQL。不幸的是,这是没有办法的


同样的代码在LINQ to对象上运行良好,因为在这种情况下,编译器当然可以安排调用您的方法。

No;这是不可能的。EF怎么知道如何将
IsMatch(…)
转换成SQL?让我困惑的是,有一个叫做“Call”的方法,它似乎是为执行类似的方法而设计的。MSDN上的示例类似于表达式callExpr=Expression.Call(Expression.Constant(“sample string”)、typeof(string.GetMethod(“ToUpper”,new Type[]{});是否只有本机方法可以处理调用?表达式树不是EF独有的;它们比EF支持更多的功能。但是
Call()
也用于
实体函数;这是不可能的。EF怎么知道如何将
IsMatch(…)
转换成SQL?让我困惑的是,有一个叫做“Call”的方法,它似乎是为执行类似的方法而设计的。MSDN上的示例类似于表达式callExpr=Expression.Call(Expression.Constant(“sample string”)、typeof(string.GetMethod(“ToUpper”,new Type[]{});是否只有本机方法可以处理调用?表达式树不是EF独有的;它们比EF支持更多的功能。但是
Call()
也用于
EntityFunctions
。我最初认为是这样的,但在查看Expression.Call方法时,似乎您能够。它需要MethodInfo和1或属性表达式的某种组合。它仅限于本地方法吗?@bsaygh:你能做什么?将方法的代码翻译成SQL?嗯,也许不能翻译成SQL。我很困惑这是怎么回事。我想.net会执行查询,然后在执行sql后应用我的代码。@b是:如果这是您想要的,那么您必须使用
IEnumerable
而不是
IQueryable
,并完全放弃表达式树。我以前尝试过使用IEnumerable,但遇到了一个障碍。似乎我需要实现一个具有Name属性的接口或基类,以便我的方法能够知道要查询的属性。虽然我可以将其应用于每个实体,但每次更新数据库映射时都会重新生成类。有没有一种不使用接口就可以实现我的目标的方法?我最初认为是这样的,但是当查看Expression.Call方法时,似乎您能够做到。它需要MethodInfo和1或属性表达式的某种组合。它仅限于本地方法吗?@bsaygh:你会的