(or any other enumerable collection of )-6ren"> (or any other enumerable collection of )-假设我有一个包含四列的 DataTable,Company(字符串)、Fund(字符串)、State(字符串)、Value(double): table1.Rows.Add("Company -6ren">
gpt4 book ai didi

linq - System.LINQ.Dynamic : Select ("new (...)") into a List (or any other enumerable collection of )

转载 作者:行者123 更新时间:2023-12-03 12:05:09 24 4
gpt4 key购买 nike

假设我有一个包含四列的 DataTable,Company(字符串)、Fund(字符串)、State(字符串)、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));

我想使用 System.LINQ.Dynamic 来构建一个动态查询,该查询对 Company、Fund 或 State 进行分组,然后按条件选择我的组作为第一列,然后 sum(value):
string groupbyvalue="Fund";
var q1= table1.AsEnumerable().AsQueryable()
.GroupBy(groupbyvalue,"it")
.Select("new ("+groupbyvalue+" as Group, Sum(Value) as TotalValue)");

在上面的查询中,选择的 groupbyvalue(Group) 将始终是一个字符串,而 sum 将始终是一个 double,所以我希望能够转换成类似 List 的东西,其中 Result 是一个具有属性 Group (string ) 和 TotalValue (double)。

我在这方面遇到了很多麻烦,任何人都可以阐明一下吗?

最佳答案

首先,您将访问当前的分组值 Key在您的 Select 子句中:

.Select("new (Key as Group, Sum(Value) as TotalValue)");

这应该使您的查询工作。更难的问题是如何转换返回的对象,它将具有继承自 DynamicClass 的动态生成的类型。 , 成静态类型。

选项 1:使用反射访问动态对象的 GroupTotalValue特性。

选项 2:使用编译的表达式树生成轻量级代码以访问 GroupTotalValue特性。

选项 3:修改动态库以支持强类型结果。事实证明这很简单:
  • ExpressionParser.Parse() ,在私有(private)字段中捕获类型参数:
    private Type newResultType;
    public Expression Parse(Type resultType)
    {
    newResultType = resultType;
    int exprPos = token.pos;
    // ...
  • 接近尾声 ExpressionParser.ParseNew() ,我们将尝试使用 newResultType在默认为动态类型之前:
    Expression ParseNew()
    {
    // ...
    NextToken();
    Type type = newResultType ?? DynamicExpression.CreateClass(properties);
    MemberBinding[] bindings = new MemberBinding[properties.Count];
    for (int i = 0; i < bindings.Length; i++)
    bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
    return Expression.MemberInit(Expression.New(type), bindings);
    }
  • 最后,我们需要 Select() 的强类型版本。 :
    public static IQueryable<TResult> Select<TResult>(this IQueryable source, string selector, params object[] values)
    {
    if (source == null) throw new ArgumentNullException("source");
    if (selector == null) throw new ArgumentNullException("selector");
    LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(TResult), selector, values);
    return source.Provider.CreateQuery<TResult>(
    Expression.Call(
    typeof(Queryable), "Select",
    new Type[] { source.ElementType, typeof(TResult) },
    source.Expression, Expression.Quote(lambda)));
    }

    与原始 Select() 的唯一变化是我们引用的地方TResult .

  • 现在我们只需要一个命名类型来返回:
        public class Result
    {
    public string Group { get; set; }
    public double TotalValue { get; set; }
    }

    您更新后的查询将如下所示:
        IQueryable<Result> res = table1.AsQueryable()
    .GroupBy(groupbyvalue, "it")
    .Select<Result>("new (Key as Group, Sum(Value) as TotalValue)");

    关于linq - System.LINQ.Dynamic : Select ("new (...)") into a List<T> (or any other enumerable collection of <T>),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1465700/

    24 4 0