I am working on the application where user can select columns he/she wants to see on the screen and which columns to group by or aggregate. So, in my LINQ section I should actually pass variables that hold column names to both group by and aggregate clause. Keep in mind that DataTable dt
may hold different data every time(e.g. Employee info, Purchase orders, Performance stats, etc). I can only get information about the data at run time via dt.Columns[i].ColumnName
and dt.Columns[i].DataType.Name
. Can any one advise how to do that, what I need is something like this:
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];
}
}
};
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.
There are several ways to do this. Here's one.
Below is a class I use pretty often called NTuple. It is the same idea as the Tuple<T>, Tuple<T1, T2>, etc classes that come with the .NET framework. However, the NTuple class is designed to hold a variable number of items. Two NTuple instances are equal if they contain the same number of values and those values are equal.
Given a set of columns
// as per OP, the list of columns to group by will be generated at runtime
IEnumerable<string> columnsToGroupBy = ...;
you can use the NTuple class to group by those columns like this:
var groups = dt.AsEnumerable()
.GroupBy(r => new NTuple<object>(from column in columnsToGroupBy select r[column]));
Here's the beef:
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;
}
}
Here's a test case:
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])));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With