C# 在简单/未命名C LINQ组联接中对内部键源排序
我知道这个问题读起来很奇怪,因为用了很多词。但这是我在学习LINQ group加入时使用的术语,我将解释它们 我正在尝试LINQ的数据是:C# 在简单/未命名C LINQ组联接中对内部键源排序,c#,linq,join,anonymous-types,C#,Linq,Join,Anonymous Types,我知道这个问题读起来很奇怪,因为用了很多词。但这是我在学习LINQ group加入时使用的术语,我将解释它们 我正在尝试LINQ的数据是: class Product { public string Name { get; set; } public int CategoryID { get; set; } } class Category { public string Name { get; set;
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},
};
而不是选择匿名类型或使用嵌套的from select子句
LINQ组联接中的外部键源是跟随关键字的数据源,内部键源是跟随join关键字的数据源
为了方便起见,我将简单组join命名为unnamed,因为我们在所选组中没有外部键源名称/Id
我试图编写一个简单的/未命名的查询,该查询将产生以下结果,首先是orderby外部键源属性,然后是orderby内部键源属性:
Unnamed Group
Cola
Tea
Unnamed Group
Mustard
Pickles
Unnamed Group
Melons
Peaches
Unnamed Group
Unnamed Group
Bok Choy
Carrots
我可以按以下方式通过外部keysource订购:
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);
}
}
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);
}
}
但它正在产生以下产出:
Unnamed group
Cola
Tea
Unnamed group
Mustard
Pickles
Unnamed group
Peaches
Melons
Unnamed group
Unnamed group
Carrots
Bok Choy
但我无法订购未命名类别组下的产品
我知道我可以通过如下方式选择匿名类型来实现这一点:
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);
}
}
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);
}
}
但是,我只想知道我是否可以在不选择匿名类型的情况下执行相同的操作。我觉得它在语法上应该与keysources和选择匿名类型上的顺序无关。因此,在查询本身中应该有如下方法来实现这一点,但它不起作用:
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;
我可能错了。但我认为如果没有完整的选择,你不可能做到这一点。我有点不同意匿名类型的选择和orderby是无关的 要么选择查询中已经提到的对象,在这种情况下不需要anon类型,要么根据它选择其他对象。如果您选择了其他内容,而不是查询前一部分给出的内容,则必须进行完全选择 IINM这在SQL中是相同的-您需要一个子查询来执行类似的操作,而不是像这样选择整个组,而是如果您想执行ORDER BY后跟TOP的操作。您可以在加入之前订购产品:
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保留了outer元素的顺序,而对于这些元素中的每一个,都保留了internal元素的匹配顺序
有些备选方案更像您的示例:
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);
我查看了您提供的链接中列出的代码,这里是您问题的解决方案。您在查询中的原始订单将只对类别进行排序,而不会查看产品。如果需要问题中描述的订单,还需要另一个子查询来订购产品:
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;
}
}
您的收藏已经在内部订购,这与此有多大关系?您可以在迭代组键和/或分组项时轻松地对它们进行排序。只有当您需要一次又一次地迭代同一个有序集合时,我才能想象预排序会带来性能上的好处。如果说您可以在这里选择一个属性,产品名称,但不能按它排序,那么不使用扩展方法就无法应用排序,正如我在问题的最后一段代码摘录中所示,甚至作为orderby category.Name,product.Name?@Mahesha999您的最后一段代码事实上,您问题中的每段代码摘录都使用扩展方法.yep,但放入明确的orderby product.Name会出现错误。当前上下文中不存在产品名称,我无法找到任何使用LINQ应用排序的方法,现在我意识到显式使用OrderBy扩展方法是唯一的解决方案。是这样吗?@Mahesha999好吧,你用OrderBy命令一个序列,然后Join连接两个序列;而且我认为在加入之前订购产品没有任何问题,因为您在加入之前也已经订购了类别。请记住,编译器会将使用simple的查询语法转换为方法语法,因此,如果将产品转换为方法语法,则不能简单地插入orderby product.Name。尽管如此,我还是添加了一些示例来对加入后的组进行排序,这些示例看起来更像您的示例。@Mahesha999是的,使用OrderBy。。。或者填写类似于。。。进入prodGroup在prodGroup orderby p中从p中选择。名称选择p是唯一的方法。但是,您当然可以编写自己的GroupBy扩展方法,该方法不依赖于隐式排序本身,甚至可以使用查询语法:-