gpt4 book ai didi

c# - 使用 ExpressionTree 生成动态查询时出错

转载 作者:太空狗 更新时间:2023-10-30 00:59:47 30 4
gpt4 key购买 nike

我的代码是对此处示例的轻微修改:

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/how-to-use-expression-trees-to-build-dynamic-queries

我正在编写一个扩展方法,允许执行 unionon 源/目标列表中的任何属性并具有以下签名

public static IEnumerable<TSource> UnionOn<TSource, TProperty>(
this IEnumerable<TSource> first,
Expression<Func<TSource, TProperty>> expression,
IEnumerable<TSource> second)
{

var finalList = new List<TSource>();
finalList.AddRange(first);

var queryableData = finalList.AsQueryable();
foreach (var item in second.ToList())
{
var propertyValue = expression.Compile().Invoke(item);

// x=>x.ExtendedPropertyId == 'guid_value'
var sourceObjectParam = Expression.Parameter(typeof(TSource), "x");
var propertyName = ((MemberExpression)expression.Body).Member.Name;

var left = Expression.Property(sourceObjectParam, propertyName);
var right = Expression.Constant(propertyValue);

var predicateBody = Expression.Equal(left, right);

MethodCallExpression whereCallExpression = Expression.Call(
typeof(Enumerable),
"Where",
new Type[] { queryableData.ElementType },
queryableData.Expression,
Expression.Lambda<Func<TSource, Boolean>>(predicateBody, new ParameterExpression[] { sourceObjectParam }));

// **** this line causes runtime error *****
IQueryable<TSource> resultsQuery = queryableData.Provider.CreateQuery<TSource>(whereCallExpression);

if (resultsQuery.ToList().Any())
finalList.Add(item);
}

return finalList;
}

在生成 resultsQuery 方法时读取异常:

System.ArgumentException: 'Argument expression is not valid

但是,当我查看 whereCallExpression 中生成的表达式的调试 View 时,它对我来说看起来不错:

.Call System.Linq.Enumerable.Where(
.Constant<System.Linq.EnumerableQuery`1[A]>(System.Collections.Generic.List`1[A]),
.Lambda #Lambda1<System.Func`2[A,System.Boolean]>)

.Lambda #Lambda1<System.Func`2[A,System.Boolean]>(A $x) {
$x.ExtendedPropertyId == .Constant<System.Guid>(fadd6b4e-8d97-404c-bcf1-
c5ebd02230a6)

任何帮助将不胜感激。

最佳答案

这段代码有很多低效之处。在处理 IEnumerable 时使用表达式并没有真正的好处小号 - Func<..>类似于标准 LINQ 的参数 Enumerable方法就足够了。

但要回答您的具体问题。异常是因为您正在调用 CreateQuery表达式返回 IEnumerable<TSource> (由于 Enumerable.Where 方法调用)而它期望(需要)IQueryable (或 IQueryable<TSource> )类型表达式。

修复很简单 - 更改 typeof(Enumerable)typeof(Queryable)在你的Expression.Call (其他参数不变)问题解决。

另请注意,当您在编译时键入 TSourceIQueryable<TSource>Expression<Func<TSource, bool>>变量,无需编写 Where调用并CreateQuery - 你可以简单地使用 Queryable.Where直接扩展方法,例如给予

var predicate = Expression.Lambda<Func<TSource, bool>>(predicateBody, sourceObjectParam);

MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { queryableData.ElementType },
queryableData.Expression,
predicate);

IQueryable<TSource> resultsQuery =
queryableData.Provider.CreateQuery<TSource>(whereCallExpression);

可以替换为

IQueryable<TSource> resultsQuery = queryableData.Where(predicate);

从而避免这样的错误。

关于c# - 使用 ExpressionTree 生成动态查询时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53529348/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com