3

こんにちは私はMS101linqの例をコーディングしています。

「JoinOperators」は、クエリ式をラムダ構文に、またはその逆にリファクタリングしようとしているため、苦労しています。

とにかく、例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
    };

そして、私はそれをラムダとしてこのように実装しようとしました:

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

何らかの理由で、この方法でサプライヤーレベルの情報にアクセスできません。を切り替えるcustomerssuppliers、顧客レベルの情報にアクセスできません。

両方のオブジェクトのフィールドレベルからプルできる過負荷はありSelectMany()ますか?

また、が2つのコレクション(および)GroupJoin()を持つオブジェクトを返すように見える理由もわかりません。どういうわけか彼らに加わることになっていないのですか?supplierscustomers

私はどのように機能するのか理解していないと思いますGroupJoin()

4

3 に答える 3

8

グループ参加で結果セレクターが間違っているため、問題が発生しました。固定クエリは次のとおりです。

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   
        });
于 2013-02-25T15:53:22.040 に答える
1

クエリ式をラムダに変換する方法を学びたい場合は、デフォルトでそれを実行できる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のコーディングと保守が簡単になると思います。

この例のGroupJoinは、(。DefaultIfEmpty句を介して)左結合を実行するために使用されます。

于 2013-02-25T15:52:33.087 に答える
1

これを試して:

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
        });
于 2013-02-25T15:52:37.653 に答える