在简单/未命名的C#LINQ组连接中排序内部键源
我知道这个问题因使用的单词而变得奇怪。 但这是我正在学习LINQ组连接的MSDN页面上使用的术语,我将解释它们。
我正在尝试LINQ的数据是:
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 categories = new List() { 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 products = new List() { 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}, };
现在的条款:
-
简单/未命名的组连接是我们直接选择组的组:
//... join product in products on category.ID equals product.CategoryID into prodGroup select prodGroup;
而不是选择匿名类型或使用嵌套的
from-select
子句。 -
LINQ group join中的外键源是一个遵循关键字的数据源, inner keysource是一个跟随
join
关键字的数据源我称简单组加入未命名 (为了方便起见),因为我们在选定的组中没有外键源名称/ Id。
我试图编写简单/未命名的查询,它将产生以下结果,首先是orderby外键源属性,然后是内部键源属性:
Unnamed Group Cola Tea Unnamed Group Mustard Pickles Unnamed Group Melons Peaches Unnamed Group Unnamed Group Bok Choy Carrots
我可以通过外键源订购如下:
var simpleGroupJoinOrderby = from category in categories orderby category.Name //orderby outer ks join product in products on category.ID equals product.CategoryID into prodGroup select prodGroup; foreach (var unnamedGroup in simpleGroupJoinOrderby) { Console.WriteLine("Unnamed group"); foreach(var product in unnamedGroup) { Console.WriteLine(" " + product.Name); } }
但它正在产生以下输出:
Unnamed group Cola Tea Unnamed group Mustard Pickles Unnamed group Peaches Melons Unnamed group Unnamed group Carrots Bok Choy
但我无法在未命名的类别组下订购产品。
我知道我可以通过选择匿名类型来做到这一点,如下所示:
var namedGroupJoinOrderBy = from category in categories orderby category.Name //order group hierarchy by name join product in products on category.ID equals product.CategoryID into prodGroup select new { Category = category.Name, Products = from prod in prodGroup orderby prod.Name //order by prodGroup.prod.Name under particular group hierarchy select prod }; foreach (var category in namedGroupJoinOrderBy) { Console.WriteLine("Category : " + category.Category); foreach (var product in category.Products) { Console.WriteLine(" " + product.Name); } }
但是我只是想知道我是否可以在不选择匿名类型的情况下做同样的事情。 我觉得它应该在语法上与“两个”键源的顺序和选择匿名类型无关。 因此,应该有一些方法在查询本身中执行此操作,如下所示,但它无法正常工作:
var simpleGroupJoinOrderby = from category in categories orderby category.Name //orderby outer ks join product in products on category.ID equals product.CategoryID into prodGroup orderby product.Name //Err: The name 'product' does not exist in the current context select prodGroup;
您可以在加入之前订购products
:
var simpleGroupJoinOrderby = from category in categories orderby category.Name join product in products.OrderBy(p => p.Name) on category.ID equals product.CategoryID into prodGroup select prodGroup;
结果是:
Unnamed group Cola Tea Unnamed group Mustard Pickles Unnamed group Melons Peaches Unnamed group Unnamed group Bok Choy Carrots
它的工作原理是因为Join
保留了外部元素的顺序,并且对于每个元素,内部匹配元素的顺序(引自MSDN )。
一些替代方案(更像你的例子):
var simpleGroupJoinOrderby = categories.OrderBy (c => c.Name) .GroupJoin(products, c => c.ID, p => p.CategoryID, (c, ps) => ps.OrderBy(p => p.Name)); var simpleGroupJoinOrderby = from category in categories orderby category.Name join product in products on category.ID equals product.CategoryID into prodGroup select prodGroup.OrderBy(g => g.Name);
我错了。 但是如果没有完全select
我认为你不能做到这一点。 我有点不同意匿名类型和order by
是无关的。
您可以select
查询中已经提到过的东西,在这种情况下您不需要anon类型,或者根据它选择其他东西。 如果您select
其他内容,而不是查询前一部分给出的内容,则必须进行完整select
。
IINM在SQL中是相同的 – 你需要一个子查询来做类似的事情(不是你要像这样选择整个组,但是如果你想要做ORDER BY
然后是TOP
)。
我查看了您提供的链接中列出的代码,这是您的问题的解决方案。 您在查询中的原始订单只会订购类别,而不会查看产品。 如果您需要在问题中描述的订单,则还需要另一个子查询来订购产品:
var simpleGroupJoinOrderby = from category in DBContext.categories orderby category.Name //orderby outer ks join product in DBContext.products on category.ID equals product.CategoryID into prodGroup select prodGroup; foreach (var unnamedGroup in simpleGroupJoinOrderby) { lblList.Text += "//Unnamed group"; var unnamedProductsGroup = unnamedGroup.OrderBy(z => z.Name).Select(group => new { name = group.Name, ID = group.CategoryID }); foreach (var product in unnamedProductsGroup) { //Console.WriteLine(" " + product.Name); lblList.Text += "|" + product.name; } }