42

拡張構文を使用して、私が持っている 2 つのリストで LINQ を使用して左結合を作成しようとしています。以下はマイクロソフトのヘルプからのものですが、ペット リストに要素がないことを示すために修正しました。私が最終的に得ているのは、0要素のリストです。これは、内部結合が行われているためだと思います。最終的に作成したいのは、3 つの要素 (3 つの Person オブジェクト) のリストで、欠落している要素には null データが入力されています。つまり、左結合です。これは可能ですか?

Person magnus = new Person { Name = "Hedlund, Magnus" };
Person terry = new Person { Name = "Adams, Terry" };
Person charlotte = new Person { Name = "Weiss, Charlotte" };

//Pet barley = new Pet { Name = "Barley", Owner = terry };
//Pet boots = new Pet { Name = "Boots", Owner = terry };
//Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
//Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

List<Person> people = new List<Person> { magnus, terry, charlotte };
//List<Pet> pets = new List<Pet> { barley, boots, whiskers, daisy };
List<Pet> pets = new List<Pet>();

// Create a list of Person-Pet pairs where 
// each element is an anonymous type that contains a
// Pet's name and the name of the Person that owns the Pet.
var query =
    people.Join(pets,
                person => person,
                pet => pet.Owner,
                (person, pet) =>
                    new { OwnerName = person.Name, Pet = pet.Name }).ToList();
4

6 に答える 6

76

拡張メソッドを使用する場合は、 GroupJoinを使用する必要があると思います

var query =
    people.GroupJoin(pets,
                     person => person,
                     pet => pet.Owner,
                     (person, petCollection) =>
                        new { OwnerName = person.Name,
                              Pet = PetCollection.Select( p => p.Name )
                                                 .DefaultIfEmpty() }
                    ).ToList();

選択式をいじる必要があるかもしれません。1対多の関係がある場合、あなたが望むようになるかどうかはわかりません。

LINQ クエリ構文を使用すると少し簡単になると思います

var query = (from person in context.People
             join pet in context.Pets on person equals pet.Owner
             into tempPets
             from pets in tempPets.DefaultIfEmpty()
             select new { OwnerName = person.Name, Pet = pets.Name })
            .ToList();
于 2009-02-08T06:04:55.533 に答える
17

結合されたオブジェクトをセットに入れてから、JPunyonが言ったようにDefaultIfEmptyを適用する必要があります。

Person magnus = new Person { Name = "Hedlund, Magnus" };
Person terry = new Person { Name = "Adams, Terry" };
Person charlotte = new Person { Name = "Weiss, Charlotte" };

Pet barley = new Pet { Name = "Barley", Owner = terry };
List<Person> people = new List<Person> { magnus, terry, charlotte };
List<Pet> pets = new List<Pet>{barley};

var results =
    from person in people
    join pet in pets on person.Name equals pet.Owner.Name into ownedPets
    from ownedPet in ownedPets.DefaultIfEmpty(new Pet())
    orderby person.Name
    select new { OwnerName = person.Name, ownedPet.Name };


foreach (var item in results)
{
    Console.WriteLine(
        String.Format("{0,-25} has {1}", item.OwnerName, item.Name ) );
}

出力:

Adams, Terry              has Barley
Hedlund, Magnus           has
Weiss, Charlotte          has
于 2009-02-08T06:50:38.250 に答える
5

この同じ問題に直面すると、次のエラー メッセージが表示されます。

結合句のいずれかの式の型が正しくありません。'GroupJoin' の呼び出しで型の推定に失敗しました。

同じプロパティ名を使用すると解決しましたが、うまくいきました。

(...)

join enderecoST in db.PessoaEnderecos on 
    new 
      {  
         CD_PESSOA          = nf.CD_PESSOA_ST, 
         CD_ENDERECO_PESSOA = nf.CD_ENDERECO_PESSOA_ST 
      } equals 
    new 
    { 
         enderecoST.CD_PESSOA, 
         enderecoST.CD_ENDERECO_PESSOA 
    } into eST

(...)

于 2009-03-02T17:08:39.487 に答える
3

これは、Fabrice (LINQ in Action の著者) によって投稿されたばかりの優れたブログ投稿で、私が尋ねた質問の内容をカバーしています。質問の読者はこれが役立つと思うので、参照用にここに置きます。

クエリ構文からメソッド/演算子構文への LINQ クエリの変換

于 2009-02-10T19:49:20.387 に答える
2

LINQ での左結合は、DefaultIfEmpty() メソッドで可能です。あなたの場合の正確な構文はありませんが...

実際には、クエリでペットをpets.DefaultIfEmpty()に変更するだけでうまくいくと思います...

編集:遅れたときに本当に答えるべきではありません...

于 2009-02-08T05:30:03.873 に答える
0

実際にデータベースがある場合、これが最も簡単な方法です。

var lsPetOwners = ( from person in context.People
                    from pets in context.Pets
                        .Where(mypet => mypet.Owner == person.ID) 
                        .DefaultIfEmpty()
                     select new { OwnerName = person.Name, Pet = pets.Name }
                   ).ToList();
于 2015-08-18T08:21:43.503 に答える