将orderby应用于C# LINQ内联接

3

我正在尝试使用这个msdn页面中的C# LINQ Joins。

虽然在组合连接中可以使用,但我无法对内部连接应用order by。

运行查询的数据如下:

    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},
    };

期望的输出结果是(按括号中的类别和产品排序):

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

我使用group-joinorderby和第二个from-select来生成以下输出,以形成组层次结构并生成普通列表:

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
            };

但是,当我在内连接(即没有使用into子句的组连接)中应用orderby时,就无法生成相同的输出。我尝试了以下几种变体:

变体#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
            };

变体#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
            };    

然而,两种变体的输出结果与不使用orderby时相同,并产生以下输出:

Cola (Beverages)
Tea (Beverages)
Mustard (Condiments)
Pickles (Condiments)
Carrots (Vegetables)
Bok Choy (Vegetables)
Peaches (Fruit)
Melons (Fruit)
问:如何使用inner-joinorderby生成所需的输出?

无论如何,要打印查询结果,可以使用以下foreach(只需更改查询变量名称):

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

6
您的第二个选项应该可以很好地工作。
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
            };

输出:

[
    { 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" }
]

从您的输出中我看到项目保持原始顺序。请确保在查询中应用了orderby操作符。


你的意思是在变体2中交换“产品”和“类别”吗? - Mahesha999
@Mahesha999,它正在工作(我复制并粘贴了控制台输出)。此外,你的第二种方法也有效。请确保应用了正确的 orderby 运算符。 - Sergey Berezovskiy

2

将Orderby从主Linq中移除,使用

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

我认为这应该能给你所需的输出结果。

哎呀,这对我来说有点难度,那些扩展方法和Lambda表达式 :'( 不可以只用LINQ查询完成吗?虽然我很感激你的回答,请不要删除它。 - Mahesha999
另一个选项可能是添加第二个Linq,我会在我的答案中添加。 - David Molyneux
@DavidMolyneux 没有必要使用额外的方法语法进行排序 - 您可以直接在查询中应用排序。此外,也没有必要为排序编写额外的查询。 - Sergey Berezovskiy
@SergeyBerezovskiy从答案中删除了这个。我个人更喜欢将顺序分开到主连接,因为您可以在代码的其他位置使用相同的连接查询不同的顺序。 - David Molyneux
@DavidMolyneux 我会使用单个查询,除非你在几个地方真的需要不同的排序。YAGNI :) - Sergey Berezovskiy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接