c# – 使用ExpressionTree生成动态查询时出错
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 使用ExpressionTree生成动态查询时出错,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2989字,纯文字阅读大概需要5分钟。
内容图文
我的代码是这里的示例的一个小修改:
我正在编写一个扩展方法,允许在源/目标列表中的任何属性上执行union,并具有以下签名
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中查看生成的表达式的debugview时,它看起来很好:
.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)
}
任何帮助都感激不尽.
解决方法:
这段代码中存在许多低效率.使用IEnumerables时使用表达式并没有什么好处 – Func< ..>类似于标准LINQ的参数Enumerable方法就足够了.
但要回答你的具体问题.例外情况是因为您使用返回IEnumerable< TSource>的表达式调用CreateQuery. (由于Enumerable.Where方法调用),它期望(需要)IQueryable(或IQueryable< TSource>)类型表达式.
修复很简单 – 在Expression.Call中将typeof(Enumerable)更改为typeof(Queryable)(其他参数不变),问题就会消失.
还要注意,当你有编译时类型TSource和IQueryable< TSource>和表达式< 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生成动态查询时出错全部内容,希望文章能够帮你解决c# – 使用ExpressionTree生成动态查询时出错所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。