web-dev-qa-db-ja.com

単一結合で複数のフィールドに対してLINQで結合する方法

私はLINQ2DataSetクエリを実行する必要があります。

var result = from x in entity
join y in entity2 
       on x.field1 = y.field1 
and 
          x.field2 = y.field2

私はまだ適切な解決策を見つけました(where節に追加の制約を追加することができますが、これは適切な解決策には程遠いか、 this 解決策を使いますが、それは等価結合を仮定します)。

LINQでは、単一の結合で複数のフィールドに結合することは可能ですか?

EDIT

var result = from x in entity
             join y in entity2
             on new { x.field1, x.field2 } equals new { y.field1, y.field2 }

上記の等結合を仮定して私が参照した解決策です。

さらにEDIT

私の最初の例はエクイジョインであるという批判に答えるために、私は現在の要件はエクイジョインであり、私はすでに上で言及した解決策を採用していることを認めます。

しかし、私はLINQでどのような可能性とベストプラクティスを採用するべきかを理解しようとしています。私はもうすぐテーブルIDを使って日付範囲クエリを結合する必要があるでしょう、そして単にその問題を先取りしていました、それは私がwhere節に日付範囲を追加しなければならないように見えます。

いつものように、与えられたすべての提案やコメントをありがとう

227
johnc

匿名タイプのソリューションは正常に機能するはずです。 LINQ canは、(とにかく結合句を使用した)等結合のみを表し、実際、元のクエリに基づいてとにかく表現したいということです。

特定の理由で匿名タイプのバージョンが気に入らない場合は、その理由を説明する必要があります。

元々求めていた以外のことをしたい場合は、本当にやりたいことの例を挙げてください。

編集:質問の編集への応答:はい、「日付範囲」結合を行うには、代わりにwhere句を使用する必要があります。これらはセマンティック上は同等であるため、利用可能な最適化の問題です。 Equijoinsは、内部シーケンスに基づいてルックアップを作成することにより、シンプルな最適化を提供します(LINQ to DataSetsにはLINQ to DataSetsが含まれます)。キーからそのキーに一致するエントリのシーケンスへのハッシュテーブルと考えてください。

日付範囲でこれを行うのは少し難しくなります。ただし、「日付範囲結合」の意味に応じて、何かできることがありますsimilar-日付の "バンド"(たとえば、1年に1回)の作成を計画している場合同じ年(ただし同じ日付ではない)に発生する2つのエントリが一致する必要がある場合、そのバンドをキーとして使用するだけで実行できます。より複雑な場合、例えば結合の片側は範囲を提供し、結合の反対側は単一の日付を提供し、その範囲内に収まる場合は、wherename__節(2番目のfromname__節の後)IMOでより適切に処理されます。どちらか一方を注文して、より効率的に一致を見つけることで、特にファンキーな魔法を行うことができますが、それは多くの作業になります。パフォーマンスが問題かどうかを確認してから、そのようなことをします。

87
Jon Skeet
var result = from x in entity
   join y in entity2 on new { x.field1, x.field2 } equals new { y.field1, y.field2 }
122
KristoferA
var result = from x in entity1
             join y in entity2
             on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 }

2つのエンティティで列名が異なる場合は、これを実行する必要があります。

68
RealNapster

これを同等のメソッドチェーン構文で完成させるだけです。

entity.Join(entity2, x => new {x.Field1, x.Field2},
                     y => new {y.Field1, y.Field2}, (x, y) => x);

最後の引数(x, y) => xはあなたが選択するものですが(上記の場合はxを選択します)。

46
niieani

もっと読みやすく柔軟なオプションはWhere関数を使うことだと思います。

var result = from x in entity1
             from y in entity2
                 .Where(y => y.field1 == x.field1 && y.field2 == x.field2)

これにより、.DefaultIfEmpty()を追加することで、内部結合から左結合に簡単に変更することもできます。

29
Alexei
var result = from x in entity
             join y in entity2
             on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 }
             select new 
             {
               /// Columns
              };
9
user3966657

あなたは(下記)のようなことをすることができます

var query = from p in context.T1

        join q in context.T2

        on

        new { p.Col1, p.Col2 }

        equals

         new { q.Col1, q.Col2 }

        select new {p...., q......};
8
Perpetualcoder

結合演算子を使用すると、等結合のみを実行できます。他の演算子を使用して他の種類の結合を構築できます。実際に結合しようとしているのが、これらの方法を使用するか、where句を変更することによって簡単になるかどうかわかりません。 join句に関する文書は こちら にあります。 MSDNには 結合操作に関する記事 があり、他の結合の例への複数のリンクもあります。

7
tvanfosson

フィールド名がエンティティで異なる場合

var result = from x in entity
   join y in entity2 on 
          new {
                field1=   x.field1,
               field2 =  x.field2 
             } 
          equals
         new { 
                field1= y.field1,
                field2=  y.myfield
              }
select new {x,y});
2
Mahesh

このような完全なメソッドチェーンとして、

lista.SelectMany(a => listb.Where(xi => b.Id == a.Id && b.Total != a.Total),
                (a, b) => new ResultItem
                {
                    Id = a.Id,
                    ATotal = a.Total,
                    BTotal = b.Total
                }).ToList();
2
Adam Garner