【发布时间】:2014-02-01 05:07:58
【问题描述】:
我最近在how to write customized expression tree 上发布了一个问题(尽管我当时没有意识到这是我在问的问题)。现在我正在尝试使用 Scott Chamberlain 提供的答案来创建另一个通用方法。
我正在使用实体框架,并且有几个实体可以通过“名称”属性之类的东西进行过滤。它并不总是被称为名称,但基本上就是这样。
实际的过滤器方法比简单的包含或开头更复杂。它更像是 Starts With,然后将名称包含搜索文本的任何记录附加到列表的末尾。
由于需要执行此过滤器的实体太多,我希望能够创建一个扩展方法,将该过滤器应用于预编译查询。
我希望能够打电话
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)
}
IsMatch 只接受 2 个字符串并返回一个布尔值。这并不是该方法的最终结果,但我希望能够让一个简单版本的 IsMatch 工作,然后我会对其进行扩展。
当我对结果调用 ToList 时,我得到一个异常。
“LINQ to Entities 无法识别方法 'Boolean IsMatch(System.String, System.String)' 方法,并且该方法无法转换为存储表达式。”
从我所做的搜索中,我相信我正在尝试做的事情是可能的,我只是做错了。是我设置表达式树的方式吗?是 IsMatch 方法吗?这一切都错了吗?
【问题讨论】:
-
否;这是不可能的。 EF 应该如何知道如何将
IsMatch(...)转换为 SQL? -
让我感到困惑的是,有一个方法叫做“Call”,它似乎是为了执行这样的方法而设计的。 MSDN 上的示例看起来像 Expression callExpr = Expression.Call( Expression.Constant("sample string"), typeof(String).GetMethod("ToUpper", new Type[] { }));是否只有原生方法可以与 Call 一起使用?
-
表达式树不是 EF 独有的;它们支持比 EF 更多的功能。但
Call()也用于EntityFunctions。
标签: c# linq entity-framework expression-trees