mz1*_*378 2 c# lambda expression expression-trees entity-framework-core
我使用这段代码,但出现错误:
错误:System.ArgumentException:“...GreenPaperItem”类型的表达式不能用于方法“Boolean”的“System.Runtime.CompilerServices.Closure”类型的参数
public static Expression<Func<T, bool>> ToExpression<T>(Func<T, bool> p)
{
ParameterExpression p0 = Expression.Parameter(typeof(T));
ParameterExpression p1 = Expression.Parameter(typeof(bool));
return Expression.Lambda<Func<T, bool>>(Expression.Call(p.Method, p0, p1),
new ParameterExpression[] { p0, p1 });
}
Run Code Online (Sandbox Code Playgroud)
该表达式旨在用于 linq toEntity IQueriyable 查询:
query = query.Where(ToExpression<GreenPaperItem>(filter.GenerateFilterFunction()));
Run Code Online (Sandbox Code Playgroud)
如何转换
Func<T, bool>为Expression<Func<T, bool>>
简而言之 - 你不知道。反之亦然,通过框架Expression<TDelegate>.Compile方法提供的转换是“容易”的。但其他方法将需要执行诸如从 IL/机器代码反编译之类的操作(我想我看到了一些尝试,但不确定何时何地 =) )。
我使用过
AsQueryable()并且它有效,但是为了检查它最后是否不可枚举,我收到错误“给定的‘IQueryable’不支持生成查询字符串。” 当我想转换查询时ToQueryString()
所以基本上它不起作用(至少以你真正想要/需要的方式)。
您似乎对IQueryable表达式树和查询提供程序(尤其是 EF Core 之一)的工作方式存在一些误解。简而言之(经过一些简化)通常查询提供程序将分析传递的表达式树以执行某些操作。在 EF Core 情况下,它会将调用转换为实际的 SQL 查询,并且无法将任意方法调用转换为 SQL,这无法通过toFunc<...>返回的“转换”来修复。filter.GenerateFilterFunction()Expression<Func<...>>
您的无效尝试:
public static Expression<Func<T, bool>> ToExpression<T>(Func<T, bool> p)
{
ParameterExpression p0 = Expression.Parameter(typeof(T));
ParameterExpression p1 = Expression.Parameter(typeof(bool));
return Expression.Lambda<Func<T, bool>>(Expression.Call(p.Method, p0, p1),
new ParameterExpression[] { p0, p1 });
}
Run Code Online (Sandbox Code Playgroud)
与以下内容没有太大区别:
query.Where(gpi => filter.GenerateFilterFunction()(gpi)) // allow the compiler to do the magic for you
Run Code Online (Sandbox Code Playgroud)
这将有同样的问题 -GenerateFilterFunction返回函数查询提供程序(EF Core)一无所知,并且无法将其转换为 SQL(出于明显的原因)。
以及您从评论中的尝试:
query = query
.Where(filter.GenerateFilterFunction())
.AsQueryable();
Run Code Online (Sandbox Code Playgroud)
将导致所有内容都.Where(filter.GenerateFilterFunction())将在客户端执行,将所有内容提取到内存中,而不在数据库端进行过滤(Enumerable.Where(Func<>)将使用而不是,与之前的Queryable.Where(Expression<Func<>>)显式调用效果基本相同)。以下内容没有任何重大影响,因为它将可通过内存中的对象进行查询。观察到的行为也证明了这一点。AsEnumerable()WhereAsQueryableEntityFrameworkQueryableExtensions.ToQueryString(IQueryable)
您有多种选择:
引入GenerateFilterExpression实际构建可翻译的方法Expression<Func<T, bool>>
相当常见的方法是仅利用“动态”组合的能力Where(当您需要 AND 组合逻辑时):
if(filter.IsProp1Provided)
{
query = query.Where(e => e.Col1 == filter.Prop1);
}
if(filter.IsAnotherPropProvided)
{
query = query.Where(e => e.AnotherCol == filter.AnotherProp);
}
Run Code Online (Sandbox Code Playgroud)
PredicateBuilder从 LINQKit使用(可能除了第 2 点之外)
也可以看看:
| 归档时间: |
|
| 查看次数: |
136 次 |
| 最近记录: |