Mahesha999
Mahesha999

Reputation: 24721

Applying orderby to C# LINQ Inner join

I am trying out C# LINQ Joins from this msdn page.

I am not able to apply order by on inner join even though it works with group join.

The data on which queries are run are:

    class Product
    {
        public string Name { get; set; }
        public int CategoryID { get; set; }
    }

    class Category
    {
        public string Name { get; set; }
        public int ID { get; set; }
    }

    // Specify the first data source.
    static List<Category> categories = new List<Category>()
    { 
        new Category(){Name="Beverages", ID=001},
        new Category(){ Name="Condiments", ID=002},
        new Category(){ Name="Vegetables", ID=003},
        new Category() {  Name="Grains", ID=004},
        new Category() {  Name="Fruit", ID=005}            
    };

    // Specify the second data source.
    static List<Product> products = new List<Product>()
    {
        new Product{Name="Cola",  CategoryID=001},
        new Product{Name="Tea",  CategoryID=001},
        new Product{Name="Mustard", CategoryID=002},
        new Product{Name="Pickles", CategoryID=002},
        new Product{Name="Carrots", CategoryID=003},
        new Product{Name="Bok Choy", CategoryID=003},
        new Product{Name="Peaches", CategoryID=005},
        new Product{Name="Melons", CategoryID=005},
    };

The desired output is (list order by categories in brackets and then by product) :

Cola(Beverages)
Tea(Beverages)
Mustard(Condiments)
Pickles(Condiments)
Melons(Fruit)
Peaches(Fruit)
Bok Choy(Vegetables)
Carrots(Vegetables)

I was able to produce this output using group-join with orderby and 2nd from-select to deform group hierarchy and produce plain list as follows:

var listGroupJoinOrderBy =
            from category in categories
            join product in products on category.ID equals product.CategoryID into prodGroup
            from prod in prodGroup
            orderby category.Name, prod.Name  //first order by category name then product name
            select
            new
            {
                Category = category.Name,
                Product = prod.Name
            };

But then I am unable to produce this same output with orderby applied to inner join (that is group-join without into clause). I tried following variants:

Variant #1

var innerJoinOrderBy =
            from category in categories
            orderby category.Name    //orderby category name
            join product in products on category.ID equals product.CategoryID                
            orderby product.Name     //orderby product name
            select
            new
            {
                Category = category.Name,
                Product = product.Name
            };

Variant #2

var innerJoinOrderBy =
            from category in categories

            join product in products on category.ID equals product.CategoryID                
            orderby category.Name, product.Name     //orderby category first and then by product name
            select
            new
            {
                Category = category.Name,
                Product = product.Name
            };    

However both variants give the same output as if no orderby is used, and produces the following output:

Cola (Beverages)
Tea (Beverages)
Mustard (Condiments)
Pickles (Condiments)
Carrots (Vegetables)
Bok Choy (Vegetables)
Peaches (Fruit)
Melons (Fruit)

Q. How can I produce the desired output with inner-join and orderby?

Anyway, to print the query result one can use following foreach (just change the query variable name) :

foreach (var product in simpleInnerJoin)
{
    Console.WriteLine(product.Product + " (" + product.Category + ")");
}

Upvotes: 3

Views: 3921

Answers (2)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236228

Your second option should work fine

var innerJoinOrderBy =
            from c in categories
            join p in products on c.ID equals p.CategoryID
            orderby c.Name, p.Name
            select new {
                Category = c.Name,
                Product = p.Name
            };

Output:

[
    { Product="Cola", Category="Beverages" },
    { Product="Tea", Category="Beverages" },
    { Product="Mustard", Category="Condiments" },
    { Product="Pickles", Category="Condiments" },
    { Product="Melons", Category="Fruit" },
    { Product="Peaches", Category="Fruit" },
    { Product="Bok Choy", Category="Vegetables" },
    { Product="Carrots", Category="Vegetables" }
]

From your output I see that items go in their original order. Make sure you have applied orderby operator in query.

Upvotes: 6

David Molyneux
David Molyneux

Reputation: 304

Take the Orderby out of the main Linq and use

foreach (var product in simpleInnerJoin.Orderby(i=> i.Category.Name).ThenBy(i=>i.Product.Name))
{
    Console.WriteLine(product.Product + " (" + product.Category + ")");
}

I think this should give you the output you require.

Upvotes: 2

Related Questions