gpt4 book ai didi

C# LINQ - 如何动态构建 Group By 子句

转载 作者:太空狗 更新时间:2023-10-29 22:30:56 37 4
gpt4 key购买 nike

我正在开发一个应用程序,用户可以在其中选择他/她想在屏幕上看到的列以及要分组或聚合的列。因此,在我的 LINQ 部分中,我实际上应该将保存列名的变量传递给 group by 和 aggregate 子句。请记住,DataTable dt 每次都可能保存不同的数据(例如员工信息、采购订单、绩效统计等)。我只能在运行时通过 dt.Columns[i].ColumnNamedt.Columns[i].DataType.Name 获取有关数据的信息。任何人都可以建议如何做到这一点,我需要的是这样的:

        SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);

var query = from row in dt.AsEnumerable()
group row by new
{
foreach(DataColumn column in dt.Columns)
{
row[column.ColumnName];
}
} into grp

select new
{
foreach(DataColumn column in dt.Columns)
{
if(column.DataType.Name == "Decimal")
{
Sum(grp[column.ColumnName]);
}else{
grp[column.ColumnName];
}

}
};

最佳答案

有几种方法可以做到这一点。这是一个。

下面是我经常使用的类,称为 NTuple。它与 .NET 框架附带的 Tuple 、Tuple 等类的想法相同。然而,NTuple 类被设计用来容纳可变数量的项目。如果两个 NTuple 实例包含相同数量的值并且这些值相等,则它们相等。

给定一组列

// as per OP, the list of columns to group by will be generated at runtime
IEnumerable<string> columnsToGroupBy = ...;

您可以像这样使用 NTuple 类按这些列进行分组:

var groups = dt.AsEnumerable()
.GroupBy(r => new NTuple<object>(from column in columnsToGroupBy select r[column]));

这是牛肉:

public class NTuple<T> : IEquatable<NTuple<T>>
{
public NTuple(IEnumerable<T> values)
{
Values = values.ToArray();
}

public readonly T[] Values;

public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj))
return true;
if (obj == null)
return false;
return Equals(obj as NTuple<T>);
}

public bool Equals(NTuple<T> other)
{
if (ReferenceEquals(this, other))
return true;
if (other == null)
return false;
var length = Values.Length;
if (length != other.Values.Length)
return false;
for (var i = 0; i < length; ++i)
if (!Equals(Values[i], other.Values[i]))
return false;
return true;
}

public override int GetHashCode()
{
var hc = 17;
foreach (var value in Values)
hc = hc*37 + (!ReferenceEquals(value, null) ? value.GetHashCode() : 0);
return hc;
}
}

这是一个测试用例:

static void Main(string[] args)
{
// some sample data
var dt = new DataTable();
dt.Columns.Add("NAME", typeof(string));
dt.Columns.Add("CITY", typeof(string));
dt.Columns.Add("STATE", typeof(string));
dt.Columns.Add("VALUE", typeof(double));
dt.Rows.Add("Mike", "Tallahassee", "FL", 3);
dt.Rows.Add("Mike", "Tallahassee", "FL", 6);
dt.Rows.Add("Steve", "Tallahassee", "FL", 5);
dt.Rows.Add("Steve", "Tallahassee", "FL", 10);
dt.Rows.Add("Steve", "Orlando", "FL", 7);
dt.Rows.Add("Steve", "Orlando", "FL", 14);
dt.Rows.Add("Mike", "Orlando", "NY", 11);
dt.Rows.Add("Mike", "Orlando", "NY", 22);

// some "configuration" data
IEnumerable<string> columnsToGroupBy = new[] {"CITY", "STATE"};
string columnToAggregate = "VALUE";

// the test routine
foreach (var group in dt.AsEnumerable().GroupBy(r => new NTuple<object>(from column in columnsToGroupBy select r[column])))
{
foreach (var keyValue in group.Key.Values)
{
Debug.Write(keyValue);
Debug.Write(':');
}
Debug.WriteLine(group.Sum(r => Convert.ToDouble(r[columnToAggregate])));
}
}

关于C# LINQ - 如何动态构建 Group By 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26658978/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com