2

私はMS101Linqの例をコーディングしていますが、結合によってループが発生します;)

104は、少し複雑なグループ結合がどのように機能するかを示すことを目的としています。

var prodByCategory =
    from cat in categories
    join prod in products on cat equals prod.Category into ps
    from p in ps    // <-- ?
    select new { Category = cat, p.ProductName };

「?」のある部分 pはpsとまったく同じもののように見え、その句は前の例にはないため、私は混乱します。

そこで、method / linq構文を使用して記述しようとしましたが、まとめると次のようになります。

var prodByCategory = categories.GroupJoin(products, c => c, p => p.Category, (c, p) => new { Category = c, p.First().ProductName });

First()の呼び出しは、以前のクエリ式に含まれていないため、混乱します。

これを実行すると、最初に到達する前にpが空であるため、エラーが発生します。カテゴリリストは製品コレクションのカテゴリと完全に一致しているため、それがどのように可能かはわかりません。

foreach (var item in prodByCategory)
{
    Console.WriteLine(item.ProductName + ": " + item.Category);
}

製品にはすでにカテゴリフィールドがあります。では、クエリは何が良いのでしょうか?これは単なる学習であると思いますが、ここでの価値を理解するのに苦労しています(ただし、2つのコレクションがどのように関連しているかがわからないためかもしれません)。


アップデート:

ガートの提案で遊んだ。以下の彼の明確な説明を参照してください。マイナーなクリーンアップの後、これは機能しました:

        var prodByCategory = categories.GroupJoin(products, cat => cat, prod => prod.Category,
              (cat, prod) => new { cat, products })
           .SelectMany(x => x.products
                          , (x, p) =>
                                      new
                                      {
                                          Category = x.cat,    // x.cat.CategoryName not accessible here
                                          ProductName = p.ProductName
                                      });
4

2 に答える 2

1

流暢な構文への翻訳は正しくないと思います。そのはず:

var prodByCategory = categories.GroupJoin(products, c => c, p => p.Category, (c, p) => new  { c = c, p = p })
                         .SelectMany (ps => ps.p, (ps, p) => new  { Category = ps.c, ProductName = p.ProductName });

LinqPadを使用して、流暢な構文変換とLINQステートメントの生成されたSQLの両方を調べることをお勧めします。これは素晴らしいツールであり、私はそれを頻繁に使用しています。

私は、そのサンプルの使用が疑わしいことに同意します。

于 2013-02-22T19:58:01.393 に答える
1

あなたはそれがかなり役に立たないように見えることは正しいです。GroupJoin(またはjoin- into)は、結合とグループ化のハイブリッドを実行するために使用されます。結合の右側のアイテムは、左側のアイテム内にグループ化されます。したがって、このクエリは包括的な構文で表示されます

from cat in Categories
join prod in Products on cat equals prod.Category into products
select new { Category = cat.CategoryName, 
             Products = products.Select (p => p.ProductName) }

その流暢な構文と同等

Categories.GroupJoin(Products, cat => cat, prod => prod.Category, 
    (cat, products => new  
                 {
                    Category = cat.CategoryName, 
                    Products = products.Select (p => p.ProductName)
                 })

結果は

Beverages       Chai
                Chang
                Guaraná Fantástica
                Sasquatch Ale
                ...
Condiments      Aniseed Syrup
                Chef Anton's Cajun Seasoning
                Chef Anton's Gumbo Mix
                Grandma's Boysenberry Spread
                ...

GroupJoinvs.の利点Joinは、aがsのCategory空のコレクションを持つことができることProductです。これは、SQLでは外部結合に類似しています。


join-のinto後に続く効果はfrom、グループ化された構造が再び平坦化されることです。それで

from cat in Categories
join prod in Products on cat equals prod.Category into ps
from p in ps
select new { Category = cat.CategoryName, p.ProductName }

同等のもので

Categories.GroupJoin(Products, cat => cat, prod => prod.Category, 
      (cat, products) => new {cat, products})
   .SelectMany(x => x.products
                  , (x, p) => 
                              new  
                              {
                                  Category = x.cat.CategoryName, 
                                  ProductName = p.ProductName
                              })

を生成します

Category        ProductName
--------------- ----------------------------------------
Beverages       Chai
Beverages       Chang
Condiments      Aniseed Syrup
Condiments      Chef Anton's Cajun Seasoning
Condiments      Chef Anton's Gumbo Mix
Condiments      Grandma's Boysenberry Spread
Produce         Uncle Bob's Organic Dried Pears
Condiments      Northwoods Cranberry Sauce
Meat/Poultry    Mishi Kobe Niku
...

これは、最初に単純な結合を使用するのと同じです。

したがって、この部分from p in psは本質的にクエリを変更するべきではないように見えます。しかし、それは偽装SelectManyです!これは、このような無邪気な小さな声明にとって非常に重要な変更です。私は流暢な構文に縛られていませんが、「包括的な」構文が実際に何が起こっているのかを隠すことがあります。これはバグを生成するための優れた方法です。

于 2013-02-22T21:04:57.197 に答える