Linq SelectMany
本文关键字:SelectMany Linq | 更新日期: 2023-09-27 18:01:05
嗨,我正在通过MS 101 linq示例进行编码。
";JoinOperators"这给我带来了困难,因为我正试图将查询表达式重构为lambda语法,反之亦然。
无论如何,在示例105中,我看到了以下查询表达式:
var supplierCusts =
from sup in suppliers
join cust in customers on sup.Country equals cust.Country into cs
from c in cs.DefaultIfEmpty() // DefaultIfEmpty preserves left-hand elements that have no matches on the right side
orderby sup.SupplierName
select new
{
Country = sup.Country,
CompanyName = c == null ? "(No customers)" : c.CompanyName,
SupplierName = sup.SupplierName
};
我尝试以这种方式将其实现为lambda:
// something is not right here because the result keeps a lot of "Join By" stuff in the output below
var supplierCusts =
suppliers.GroupJoin(customers, s => s.Country, c => c.Country, (s, c) => new { Customers = customers, Suppliers = suppliers })
.OrderBy(i => i.Suppliers) // can't reference the "name" field here?
.SelectMany(x => x.Customers.DefaultIfEmpty(), (x, p) => // does the DefaultIfEmpty go here?
new
{
Country = p.Country,
CompanyName = x == null ? "(No customers)" : p.CompanyName,
SupplierName = p // not right: JoinOperators.Program+Customer ... how do I get to supplier level?
});
由于某种原因,我无法通过这种方式访问供应商级别的信息。当我用suppliers
切换出customers
时,我无法访问客户级别的信息。
是否存在SelectMany()
的过载,使我可以从两个对象的字段级别提取?
此外,我不明白为什么GroupJoin()
似乎返回了一个具有两个集合(suppliers
和customers
(的对象。它不是应该以某种方式加入他们吗?
我想我不明白GroupJoin()
是怎么工作的。
您在组联接中使用了错误的结果选择器,这就是问题的根源。这里是固定查询:
var supplierCusts =
suppliers
.GroupJoin(customers,
sup => sup.Country,
cust => cust.Country,
(sup, cs) => new { sup, cs })
.OrderBy(x => x.sup.Name)
.SelectMany(x => x.cs.DefaultIfEmpty(), (x, c) =>
new
{
Country = x.sup.Country,
CompanyName = c == null ? "(No customers)" : c.CompanyName,
SupplierName = x.sup.Name
});
如果您想学习将查询表达式转换为lambda,我建议您查看LinqPad,它在默认情况下可以做到这一点。例如,您的查询翻译如下:
Suppliers
.GroupJoin (
Customers,
sup => sup.Country,
cust => cust.Country,
(sup, cs) =>
new
{
sup = sup,
cs = cs
}
)
.SelectMany (
temp0 => temp0.cs.DefaultIfEmpty (),
(temp0, c) =>
new
{
temp0 = temp0,
c = c
}
)
.OrderBy (temp1 => temp1.temp0.sup.CompanyName)
.Select (
temp1 =>
new
{
Country = temp1.temp0.sup.Country,
CompanyName = (temp1.c == null) ? "(No customers)" : temp1.c.CompanyName,
SupplierName = temp1.temp0.sup.CompanyName
}
)
话虽如此,我通常发现SelectMany使用查询语法而不是lambda语法更容易编码和维护。
本例中的GroupJoin用于完成左联接(通过.DefaultIfEmpty子句(。
试试这个:
var supplierCusts =
suppliers.GroupJoin(customers, s => s.Country, c => c.Country, (s, c) => new { Supplier = s, Customers = c })
.OrderBy(i => i.Supplier.SupplierName)
.SelectMany(r => r.Customers.DefaultIfEmpty(), (r, c) => new
{
Country = r.Supplier.Country,
CompanyName = c == null ? "(No customers)" : c.CompanyName,
SupplierName = r.Supplier.SupplierName
});