p.Person
テーブルのこの種のクエリに外部結合を実装しようとしています。どうすればいいですか?
この例は http://ashishware.com/DSLinqExample.shtml からの引用です
var onlyinfo = p.Person
.Where(n => n.FirstName.Contains('a'))
.Join(p.PersonInfo,
n => n.PersonId,
m => m.PersonId,
(n, m) => m)
.ToArray<Persons.PersonInfoRow>();
通常、LINQの左結合はグループ結合でモデル化され、場合によってはDefaultIfEmpty
およびSelectMany
と組み合わせて使用されます。
var leftJoin = p.Person.Where(n => n.FirstName.Contains("a"))
.GroupJoin(p.PersonInfo,
n => n.PersonId,
m => m.PersonId,
(n, ms) => new { n, ms = ms.DefaultIfEmpty() })
.SelectMany(z => z.ms.Select(m => new { n = z.n, m }));
これにより、ペアのシーケンス(n、m)が得られます。ここで、n
はp.Person
からのエントリであり、m
はp.PersonInfo
からのエントリですが、m
一致がない場合はnullになります。
(それは完全にテストされていない、ところで-とにかくあなたにアイデアを与えるはずです:)
左外部結合の場合は、次のクエリを試してください。これはテストされています
var leftJoin = Table1
.GroupJoin(
inner: Table2,
outerKeySelector: t1 => t1.Col1,
innerKeySelector: t2 => t2.Col2,
resultSelector: ( t1, t2Rows ) => new { t1, t2Rows.DefaultIfEmpty() }
)
.SelectMany( z =>
z.t2Rows.Select( t2 =>
new { t1 = z.t1, t2 = t2 }
)
);
誰かがこの質問に遭遇し、これを達成するための拡張メソッドが必要な場合は、他の回答と同じアプローチを使用して作成しました。通常の結合拡張メソッドと同じシグネチャを持っています。
public static IEnumerable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector)
{
return outer
.GroupJoin(inner, outerKeySelector, innerKeySelector, (outerObj, inners) =>
new
{
outerObj,
inners= inners.DefaultIfEmpty()
})
.SelectMany(a => a.inners.Select(innerObj => resultSelector(a.outerObj, innerObj)));
}