【问题标题】:Linq SelectManyLinq 多选
【发布时间】:2013-02-25 15:40:29
【问题描述】:

您好,我正在编写 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() 似乎返回了一个包含 2 个集合(supplierscustomers)的对象。不应该以某种方式加入他们吗?

我想我不明白GroupJoin() 的工作原理。

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    您在组加入时有错误的结果选择器,这就是问题开始的地方。这是固定查询:

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

    【讨论】:

    • 每次我尝试这样的查询时,都会收到错误消息,“'GroupJoin' 操作必须后跟 'SelectMany' 操作,其中集合选择器正在调用 'DefaultIfEmpty' 方法。”那是怎么回事?
    • @Boydski 以前从未遇到过该错误。您能否将您的问题作为问题发布,并附上重现步骤?
    【解决方案2】:

    如果您想学习将查询表达式转换为 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 子句)。

    【讨论】:

      【解决方案3】:

      试试这个:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-19
        • 1970-01-01
        • 2011-08-31
        • 2010-11-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多