【发布时间】:2010-10-07 22:05:18
【问题描述】:
好的,我承认我还没有完全“获得” lambda 表达式和 LINQ 表达式树。我正在做的很多事情都是剪切和粘贴,看看什么是有效的。我查看了很多文档,但还没有找到我的“啊哈”时刻。
话虽这么说......
我正在尝试将 GroupBy 表达式动态添加到我的 Linq 表达式中。我在这里关注了这个问题: Need help creating Linq.Expression to Enumerable.GroupBy
并尝试实现我在那里看到的内容。
首先,我的数据库有实体类,还有一个名为ObjCurLocViewNormalized 的表
我有一个方法可以进行初始调用,
public IQueryable<ObjCurLocViewNormalized> getLocations()
{
IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
select loc);
return res;
}
所以我可以打电话:
IQueryable<MetAmericanLinqDataModel.ObjCurLocViewNormalized> locations = american.getLocations();
目前没有问题。
现在,我想按任意列进行分组,调用如下:
var grouped = locations.addGroupBy(childLocationFieldName);
现在,我有一个方法:
static public System.Linq.IQueryable<System.Linq.IGrouping<string, TResult>> addGroupBy<TResult>(this IQueryable<TResult> query, string columnName)
{
var providerType = query.Provider.GetType();
// Find the specific type parameter (the T in IQueryable<T>)
var iqueryableT = providerType.FindInterfaces((ty, obj) => ty.IsGenericType && ty.GetGenericTypeDefinition() == typeof(IQueryable<>), null).FirstOrDefault();
var tableType = iqueryableT.GetGenericArguments()[0];
var tableName = tableType.Name;
var data = Expression.Parameter(iqueryableT, "query");
var arg = Expression.Parameter(tableType, tableName);
var nameProperty = Expression.PropertyOrField(arg, columnName);
var lambda = Expression.Lambda<Func<TResult, string>>(nameProperty, arg);
var expression = Expression.Call(typeof(Enumerable),
"GroupBy",
new Type[] { tableType, typeof(string) },
data,
lambda);
var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg); // this is the line that produces the error I describe below
var result = query.GroupBy(predicate).AsQueryable();
return result;
}
所有这些都可以编译,但是当我运行它时,我得到了错误:
System.ArgumentException: Expression of type 'System.Collections.Generic.IEnumerable`1[System.Linq.IGrouping`2[System.String,MetAmericanLinqDataModel.ObjCurLocViewNormalized]]' cannot be used for return type 'System.String'
错误来自这一行:
var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg);
我正在从成功的工作中复制和调整这段代码,我在动态添加 Where 子句到表达式中所做的工作。所以我有点在黑暗中刺伤。
如果有人可以帮助阐明这一点,显然发布完整的工作代码并为我做所有的想法会很棒:),但如果你能说明为什么这是错误的,或者如何围绕这些概念来思考一下,那就太好了。如果您可以指出真正有助于弥合 lambda 表达式基础知识和构建动态表达式树之间差距的文档,那就太好了。我的知识显然存在很大的漏洞,但我认为这些信息可能对其他人有用。
感谢大家的时间,当然如果我在别处找到答案,我会在这里发布。
再次感谢。
唐
【问题讨论】:
-
为什么你的
predicate行使用Func<TResult, string>?您的表达返回一个IGrouping,它不是string。 -
感谢柯克,我试过:将行更改为: var predicate = Expression.Lambda
>>(expression, arg);但现在我收到编译错误:错误 5 无法将类型 'System.Linq.IQueryable ,TResult>>' 隐式转换为 'System.Linq.IQueryable>'。存在显式转换(您是否缺少演员表?)。这是写你告诉我的错误的方式吗? -
主要问题是您将
.GroupBy的调用与传递给it 的lambda 谓词混淆了。目前没有时间进一步回答,但如果这个问题在一个小时后仍未得到解答,我会进行更彻底的测试。 -
啊,这个错误与返回类型不匹配有关。但我不认为我想更改返回类型,是吗?
标签: linq expression-trees