动态将GroupBy添加到Lambda表达式

编程入门 行业动态 更新时间:2024-10-25 04:20:56
本文介绍了动态将GroupBy添加到Lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

好吧,我承认我还没有完全得到" lambda表达式和LINQ表达式树.我正在做的很多事情都是剪切和粘贴,然后看看有什么用.我查看了很多文档,但是仍然找不到我的"aha"时刻.

话虽如此...

我试图将GroupBy表达式动态添加到Linq表达式中.我在这里关注了这个问题: 需要帮助将Linq.Expression创建为Enumerable.GroupBy 并尝试实现我在那看到的东西.

首先,我有数据库的实体类,还有一个名为ObjCurLocViewNormalNormalized的表

我有一个可以进行初始调用的方法

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表达式基础知识与构建动态表达式树之间的鸿沟的文档,那将是非常不错的.我的知识上显然有很多漏洞,但是我认为这些信息可能对其他人有用.

感谢大家的宝贵时间,当然,如果我在其他地方找到答案,我会在此处发布.

再次感谢.

解决方案

解决方案应该非常简单:

public static IQueryable<IGrouping<TColumn, T>> DynamicGroupBy<T, TColumn>( IQueryable<T> source, string column) { PropertyInfo columnProperty = typeof(T).GetProperty(column); var sourceParm = Expression.Parameter(typeof(T), "x"); var propertyReference = Expression.Property(sourceParm, columnProperty); var groupBySelector = Expression.Lambda<Func<T, TColumn>>(propertyReference, sourceParm); return source.GroupBy(groupBySelector); }

假设这样的示例类:

public class TestClass { public string TestProperty { get; set; } }

您可以这样调用它:

var list = new List<TestClass>(); var queryable = list.AsQueryable(); DynamicGroupBy<TestClass, string>(queryable, "TestProperty");

Ok, I'll admit that I don't entirely "get" lambda expressions and LINQ expression trees yet; a lot of what I'm doing is cutting and pasting and seeing what works. I've looked over lots of documentation, but I still haven't found the my "aha" moment yet.

With that being said...

I'm attempting to dynamically add a GroupBy expression to my Linq expression. I followed the question here: Need help creating Linq.Expression to Enumerable.GroupBy

and tried to implement what I saw there.

First off, I've got entity classes for my database, and a table calledObjCurLocViewNormalized

I've got an method that does the initial call,

public IQueryable<ObjCurLocViewNormalized> getLocations() { IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized select loc); return res; }

so I can call:

IQueryable<MetAmericanLinqDataModel.ObjCurLocViewNormalized> locations = american.getLocations();

No problem so far.

Now, I want to group by an arbitrary column, with a call like this:

var grouped = locations.addGroupBy(childLocationFieldName);

Right now, I have a method :

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; }

All this compiles ok, but when I run it, I get the error:

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'

and the error comes from this line:

var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg);

I'm copying and adapting this code from successful work I did in dynamically added Where clauses to an expression. So I'm sort of stabbing in the dark here.

If anyone out there can help to shed some light on this, Obviously posting complete working code and doing all my thinking for me would be great :), but if you could just lay out just why this is wrong, or how to wrap my head around these concepts, that would be great. If you can point to documentation that can really help be bridge the gap between the basics of lambda expressions, and building dynamic expression trees, that would be great. There's obviously big holes in my knowledge, but I think this information could be useful to others.

thanks everyone for your time, and of course if I find the answer elsewhere, I'll post it here.

Thanks again.

Don

解决方案

The solution should be pretty simple:

public static IQueryable<IGrouping<TColumn, T>> DynamicGroupBy<T, TColumn>( IQueryable<T> source, string column) { PropertyInfo columnProperty = typeof(T).GetProperty(column); var sourceParm = Expression.Parameter(typeof(T), "x"); var propertyReference = Expression.Property(sourceParm, columnProperty); var groupBySelector = Expression.Lambda<Func<T, TColumn>>(propertyReference, sourceParm); return source.GroupBy(groupBySelector); }

Assuming a sample class like this:

public class TestClass { public string TestProperty { get; set; } }

You invoke it like this:

var list = new List<TestClass>(); var queryable = list.AsQueryable(); DynamicGroupBy<TestClass, string>(queryable, "TestProperty");

更多推荐

动态将GroupBy添加到Lambda表达式

本文发布于:2023-10-30 12:01:04,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1542790.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:表达式   动态   GroupBy   Lambda

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!