To group στο LINQ δεν δουλεύει όπως το group στην SQL. Στο by δίνεις ένα function το οποίο δημιουργεί το κλειδί με το οποίο θα δημιουργηθούν τα groupings. Έτσι, μπορείς να δώσεις ένα τύπο ή να δημιουργήσεις ένα καινούριο αντικείμενο για κλειδί. Αυτό φαίνεται και από τα παραδείγματα στο
documentation του group clause.
Για να δημιουργήσεις ένα grouping βασισμένο σε δύο ή περισσότερα πεδία, μπορείς να δημιουργήσεις ένα anonymous type με τα πεδία που χρειάζεσαι όπως παρακάτω:
var groupQuery1 = from product in products
group product by new {product.TypeID, product.CategoryID} into categories
select categories;
To categories είναι ένα αντικείμενο IGrouping με ένα property Key το οποίο περιέχει τα TypeID, Category ID. Έτσι μπορείς να κάνεις άλλο ένα επίπεδο grouping, ομαδοποιώντας πλέον κατά TypeID ή κατά Category ID:
var groupQuery = from product in products
group product by new {product.TypeID, product.CategoryID} into categories
group categories by categories.Key.TypeID into types
select types;
Για να τυπώσεις τα διάφορα groups θα χρειαστείς τρία foreach, όπως παρακάτω:
foreach (var types in groupQuery)
{
Console.WriteLine("TypeID: {0}",types.Key);
foreach (var category in types)
{
Console.WriteLine("\tCategoryID: {0}", category.Key.CategoryID);
foreach (var product in category)
{
Console.WriteLine("\t\t{0} {1} {2}", product.TypeID, product.CategoryID, product.Name);
}
}
}
Το products είναι ένα array από Product, το οποίο με τη σειρά του περιέχει τα properties Name, TypeID, CategoryID.
Αντί για το σύνθετο κλειδί θα μπορούσα να είχα δώσει ένα expression όπως στα παραδείγματα του group, π.χ. TypeID %10 για να ομαδοποιήσω με βάση το τελευταίο ψηφίο του TypeID. Αν ομαδοποιούσα αρχεία ή blobs, το group θα μπορούσε να είναι το SHA256 hash του blob, για να βρω ποιά blobs είναι διπλά.
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos