web-dev-qa-db-ja.com

SelectとSelectManyの違い

私はSelectSelectManyの違いを探してきましたが、適切な答えを見つけることができませんでした。 LINQ To SQLを使用するときの違いを学ぶ必要がありますが、私が見つけたのは標準的な配列の例だけです。

誰かがLINQ To SQLの例を提供できますか?

919
Tarik

SelectManyは、リストのリストを返すクエリを統合します。例えば

public class PhoneNumber
{
    public string Number { get; set; }
}

public class Person
{
    public IEnumerable<PhoneNumber> PhoneNumbers { get; set; }
    public string Name { get; set; }
}

IEnumerable<Person> people = new List<Person>();

// Select gets a list of lists of phone numbers
IEnumerable<IEnumerable<PhoneNumber>> phoneLists = people.Select(p => p.PhoneNumbers);

// SelectMany flattens it to just a list of phone numbers.
IEnumerable<PhoneNumber> phoneNumbers = people.SelectMany(p => p.PhoneNumbers);

// And to include data from the parent in the result: 
// pass an expression to the second parameter (resultSelector) in the overload:
var directory = people
   .SelectMany(p => p.PhoneNumbers,
               (parent, child) => new { parent.Name, child.Number });

.NETでのライブデモFiddle

1437
Mike Two

Select manyはSQLの クロスジョイン操作に似ています それがクロス積をとるところ。
たとえば、

Set A={a,b,c}
Set B={x,y}

次のセットを取得するために使用できる多くの選択

{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }

ここで、集合Aと集合Bの要素から作ることができるすべての可能な組み合わせを取ります。

これはあなたが試すことができるLINQの例です。

List<string> animals = new List<string>() { "cat", "dog", "donkey" };
List<int> number = new List<int>() { 10, 20 };

var mix = number.SelectMany(num => animals, (n, a) => new { n, a });

ミックスは以下のような平らな構造の要素を持ちます。

{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}
162

enter image description here

var players = db.SoccerTeams.Where(c => c.Country == "Spain")
                            .SelectMany(c => c.players);

foreach(var player in players)
{
    Console.WriteLine(player.LastName);
}
  1. デギア
  2. アルバ
  3. コスタ
  4. ヴィラ
  5. ブスケ

...

102
AlejandroR

SelectMany()を使用すると、多次元シーケンスを折りたたむことができます。そうしないと、2番目のSelect()またはループが必要になります。

詳細はこちら ブログ投稿 で。

73

SelectManyにはいくつかのオーバーロードがあります。そのうちの1つでは、階層を移動しながら、親と子の間の関係を追跡できます。

League -> Teams -> Playerという構造になっているとします。

あなたは簡単にプレイヤーのフラットコレクションを返すことができます。しかし、あなたはその選手が所属するチームへの言及を失うかもしれません。

幸い、そのような目的のために過負荷があります:

var teamsAndTheirLeagues = 
         from helper in leagues.SelectMany
               ( l => l.Teams
                 , ( league, team ) => new { league, team } )
                      where helper.team.Players.Count > 2 
                           && helper.league.Teams.Count < 10
                           select new 
                                  { LeagueID = helper.league.ID
                                    , Team = helper.team 
                                   };

前の例は DanのIK blog からの抜粋です。ぜひご覧ください。

33
roland

私は、SelectManyが結合ショートカットのように機能することを理解しています。

だからあなたはできる:

var orders = customers
             .Where(c => c.CustomerName == "Acme")
             .SelectMany(c => c.Orders);
19
Nathan Koop

Selectは、ソース要素から結果要素への単純な一対一の投影です。クエリ式に複数のfrom句がある場合は、Select-Manyが使用されます。元のシーケンスの各要素は、新しいシーケンスを生成するために使用されます。

12
Alexandr

一部のSelectManyは必要ないかもしれません。以下の2つのクエリで同じ結果が得られます。

Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)

Orders.Where(o=>o.Customer.Name=="Tom")

一対多の関係では、

  1. 「1」から開始すると、SelectManyが必要になります。
  2. 「多」から始まる場合は、SelectManyは必要ありません。 ( それでも「1」からフィルタリングできる 、これも標準の結合クエリよりも簡単です)

from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o
7
Rm558

あまりにも技術的にならずに - 多くの組織を持ち、それぞれに多くのユーザーを持つデータベース -

var orgId = "123456789";

var userList1 = db.Organizations
                   .Where(a => a.OrganizationId == orgId)
                   .SelectMany(a => a.Users)
                   .ToList();

var userList2 = db.Users
                   .Where(a => a.OrganizationId == orgId)
                   .ToList();

両方とも 同じ - 選択された組織の/ ApplicationUserリストを返します。

組織からユーザーへの最初の "プロジェクト"、2番目のユーザーから直接ユーザーテーブルへのクエリを実行します。

4
RickL

機能的なプログラマーを助けるための別の見方をしてください。

  • Selectmapです
  • SelectManybindです(またはScala/Kotlinの人々の場合はflatMap
2
Matt Klein

クエリが文字列(charの配列)を返すと、より明確になります。

たとえば、リスト「フルーツ」に「アップル」が含まれているとします。

'Select'は文字列を返します。

Fruits.Select(s=>s) 

[0]: "Apple"

'SelectMany'は文字列を平坦化します。

Fruits.SelectMany(s=>s)

[0]: 97  'a'
[1]: 112 'p'
[2]: 112 'p'
[3]: 108 'l'
[4]: 101 'e'
2

サブ配列オブジェクトのデータを累積するためにSelectMany + Selectを使用する方法のもう1つの例。

ユーザーに電話をかけているとします。

class Phone { 
    public string BasePart = "555-xxx-xxx"; 
}

class User { 
    public string Name = "Xxxxx";
    public List<Phone> Phones; 
}

今、私たちはすべてのユーザーのすべての携帯電話のBasePartsを選択する必要があります。

var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();
0
KEMBL