views:

275

answers:

2

I have been a programmer for some years now but I am a
newcomer to LINQ and C# so forgive me if my question sounds
particularly stupid.

I hope someone may be able to point me in the right
direction. My task is to come up with the ability to form a
dynamic multiple group by linq query within a c# script using
a generic list as a source.

For example, say I have a list containing multiple items with the following
structure:

FieldChar1 - character
FieldChar2 - character
FieldChar3 - character
FieldNum1 - numeric
FieldNum2 - numeric

In a nutshell I want to be able to create a LINQ query that
will sum FieldNum1 and FieldNum2 grouped by any one, two or
all three of the FieldChar fields that will be decided at
runtime depending on the users requirements as well as selecting the FieldChar fields in the same query.

I have the dynamic.cs in my project which icludes a GroupByMany extension method but I have to admit I am really not sure how to put these to use. I am able to get the desired results if I use a query with hard-wired group by requests but not dynamically.

Apologies for any erroneous nomenclature, I am new to this language but any advice would be most welcome.

Many thanks

Alex

+1  A: 

Here is the basic GroupBy example. Let's say we have a simple class like this:

public class Person
{
    public string Name { get; set; }

    public int Age { get; set; }

    public char Sex { get; set; }
}

Then, you can use GroupBy like this:

var people = new List<Person> {
    new Person { Name = "Joe", Age = 30, Sex = 'M' },
    new Person { Name = "Liz", Age = 22, Sex = 'F' },
    new Person { Name = "Jim", Age = 22, Sex = 'M' },
    new Person { Name = "Alice", Age = 30, Sex = 'F' },
    new Person { Name = "Jenny", Age = 22, Sex = 'F' }
};
var groups = people.GroupBy(p => p.Age);

foreach (var group in groups)
{
    foreach (var person in group)
        Console.WriteLine(person.Name + " - " + person.Age);
}

As for grouping by multiple properties, see these:
http://weblogs.asp.net/zeeshanhirani/archive/2008/05/07/group-by-multiple-columns-in-linq-to-sql.aspx
http://stackoverflow.com/questions/1225710/linq-to-dataset-multiple-group-by-on-a-data-table

Basically, it is the same syntax with an anonymous type, for example:

var groups = people.GroupBy(p => new { p.Age, p.Sex });

Note that you may be looking for using multiple OrderBys:

var query = people.OrderBy(p => p.Age).ThenBy(p => p.Sex);
//You can have unlimited ThenBy's

Also note that the result of the last GroupBy statement and the result of this OrderBy statement is NOT the same.

Venemo
Many thanks for your reply. I do appreciate it and gives me something new to look at. But is it possible to get your example of...var groups = people.GroupBy(p => new { p.Age, p.Sex });into a line of code where the group by clause (p.Age, p.Sex) can be substituted by a variable string built up beforehand which could be any combination of Age and/or Sex? I am coming from a FoxPro/SQL background where you can dynamically build up your query using string concatenation. Again I appreciate your help.
FordPrefect141
@FordPerfect141 - With LINQ, you can't really just concatenate strings, because LINQ needs to be strongly typed. You can achieve something similar by creating such an expression dynamically.
Venemo
Ah-ha. So in your example if the user wanted to group sometimes by sex and age, and sometimes just by age how would you go about it without actually hard coding the group by clause? I apologise again, this is all new to me. Many thanks again.
FordPrefect141
A: 

GroupBy(groupByName + " " + groupByDirection, new {})

So you could pass in groupByName and groupByDirection, when you're stepping through, you might see something like

GroupBy("lastName desc", new{})

or

GroupBy("firstName asc", new{})

taylonr