System.LINQ.Dynamic:选择(“new (...)”)到列表中(或的任何其他可枚举集合)
假设我有一个包含四列的 DataTable,Company(字符串)、Fund(字符串)、State(字符串)、Value(双精度):
table1.Rows.Add("Company 1","Fund 1","NY",100));
table1.Rows.Add("Company 2","Fund 1","CA",200));
table1.Rows.Add("Company 3","Fund 1","FL",300));
table1.Rows.Add("Company 4","Fund 2","CA",400));
table1.Rows.Add("Company 5","Fund 1","NY",500));
table1.Rows.Add("Company 6","Fund 2","CA",600));
table1.Rows.Add("Company 7","Fund 3","FL",700));
我想使用 System.LINQ.Dynamic 构建一个动态查询,该查询对 Company、Fund 进行分组,或 State,然后选择我的 group by criteria 作为第一列,和 sum(value):
string groupbyvalue="Fund";
var q1= table1.AsEnumerable().AsQueryable()
.GroupBy(groupbyvalue,"it")
.Select("new ("+groupbyvalue+" as Group, Sum(Value) as TotalValue)");
在上面的查询中,所选的 groupbyvalue (组)将始终是一个字符串,总和将始终是一个双精度,所以我希望能够转换为类似 List 的内容,其中 Result 是一个具有 Group (字符串)和 TotalValue (双精度)属性的对象。
我在这方面遇到了很多麻烦,有人可以解释一下吗?
Say I have a DataTable with four columns, Company (string), Fund (string), State (string), Value(double):
table1.Rows.Add("Company 1","Fund 1","NY",100));
table1.Rows.Add("Company 2","Fund 1","CA",200));
table1.Rows.Add("Company 3","Fund 1","FL",300));
table1.Rows.Add("Company 4","Fund 2","CA",400));
table1.Rows.Add("Company 5","Fund 1","NY",500));
table1.Rows.Add("Company 6","Fund 2","CA",600));
table1.Rows.Add("Company 7","Fund 3","FL",700));
I want to use System.LINQ.Dynamic to build a dynamic query which groups on either Company, Fund, or State, and then selects my group by criteria as the first column, and sum(value):
string groupbyvalue="Fund";
var q1= table1.AsEnumerable().AsQueryable()
.GroupBy(groupbyvalue,"it")
.Select("new ("+groupbyvalue+" as Group, Sum(Value) as TotalValue)");
In the above query, the selected groupbyvalue (Group) will always be a string, and the sum will always be a double, so I want to be able to cast into something like a List, where Result is an object with properties Group (string) and TotalValue (double).
I'm having a lot of trouble with this, can anyone shed some light?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,您将在 Select 子句中将当前分组的值作为
Key
进行访问:这将使您的查询正常工作。更难的问题是如何将返回的对象(该对象具有继承自 DynamicClass 的动态生成类型)转换为静态类型。
选项 1:使用反射来访问动态对象的
Group
和TotalValue
属性。选项 2:使用编译的表达式树进行轻量级代码生成,以访问
Group
和TotalValue
属性。选项 3:修改动态库以支持强类型结果。事实证明这相当简单:
在
ExpressionParser.Parse()
中,捕获私有字段中的类型参数:靠近
ExpressionParser.ParseNew()
的末尾,我们将在默认为动态类型之前尝试使用newResultType
:Finally ,我们需要
Select()
的强类型版本:与原始
Select()
相比,唯一的变化是我们引用TResult
的地方。现在我们只需要返回一个命名类型:
更新后的查询将如下所示:
First, you'll access the current grouped value as
Key
in your Select clause:That should make your query work. The harder question is how to turn the returned objects, which will have a dynamically generated type that inherits from
DynamicClass
, into a static type.Option 1: Use reflection to access the dynamic object's
Group
andTotalValue
properties.Option 2: Use compiled expression trees for lightweight code generation to access the
Group
andTotalValue
properties.Option 3: Modify the Dynamic library to support a strongly-typed result. This turns out to be rather simple:
In
ExpressionParser.Parse()
, capture the type argument in a private field:Near the end of
ExpressionParser.ParseNew()
, we'll try to usenewResultType
before defaulting to a dynamic type:Finally, we need a strongly typed version of
Select()
:The only changes from the original
Select()
are places we referenceTResult
.Now we just need a named type to return:
And your updated query will look like this:
我将返回的数据转换为 List;通过以下方式:
1 扩展动态linq的Select方法以支持泛型类型。请参阅此处的第一个答案
2 使用Select 方法(与 dahlbyk 答案的第一行非常相似)
如果需要多列,可以使用以下方法:
3 将数据转换为列表。
4 使用Impromptu将List转换为List
I casted returned data to List<IExampleInterface> by the following way:
1 Extend Select method of dynamic linq to support generic types. See first answer here
2 Use the Select method (very similar to first line of dahlbyk's answer)
If you need multiple columns, you can use following:
3 Convert data to list.
4 Use Impromptu to convert List to List<IExampleInterface>
另一种可能性是扩展 DLinq 的查询语言,可以在查询字符串的
new
子句中指定类型名称。我在另一个 stackoverflow 答案 中描述了 Dynamic.cs 中需要的更改。
它将允许您提出如下查询:
Another possibility is to extend query language of DLinq with the possibility to specify the type name in the
new
clause in query string.I have described the changes need in Dynamic.cs in another stackoverflow answer.
It will allow you to pose queries like the following:
另一种更简单的方法是使用 Newtonsoft.Json 使用 Json 序列化/反序列化,如下所示:
拥有一个具有所需属性的类:
在查询之后,您进行 Json 序列化,然后反序列化为你想要的数据类型:
Another, easier, way to do that is to use Json serializing/deserializing using the Newtonsoft.Json like this:
Have a class with the wanted properties:
After your query, you Json-serialize then deserialize to the data type you want: