davranış
İki listeniz olduğunu varsayalım:
Id Value
1 A
2 B
3 C
Id ChildValue
1 a1
1 a2
1 a3
2 b1
2 b2
Sahadaki Join
iki liste sizde Id
sonuç olacaktır:
Value ChildValue
A a1
A a2
A a3
B b1
B b2
Sahadaki GroupJoin
iki liste sizde Id
sonuç olacaktır:
Value ChildValues
A [a1, a2, a3]
B [b1, b2]
C []
Böylece Join
, üst ve alt değerlerin düz (tablo) bir sonucunu verir.
GroupJoin
her biri ikinci listede birleştirilmiş bir grup girdi içeren ilk listede bir girdi listesi oluşturur.
Bu yüzden SQL'de Join
eşdeğerdir INNER JOIN
: için giriş yoktur C
. While : sonuç kümesinde GroupJoin
eşdeğerdir , ancak ilgili girdilerin boş bir listesiyle (SQL sonuç kümesinde bir satır olacaktır ).OUTER JOIN
C
C - null
Sözdizimi
Öyleyse iki liste sırasıyla IEnumerable<Parent>
ve olsun IEnumerable<Child>
. (Linq to Entities için:) IQueryable<T>
.
Join
sözdizimi
from p in Parent
join c in Child on p.Id equals c.Id
select new { p.Value, c.ChildValue }
Bir dönen IEnumerable<X>
nerede X iki özelliklere sahip bir anonim türüdür Value
ve ChildValue
. Bu sorgu sözdizimi Join
başlık altındaki yöntemi kullanır .
GroupJoin
sözdizimi
from p in Parent
join c in Child on p.Id equals c.Id into g
select new { Parent = p, Children = g }
An dönen IEnumerable<Y>
Y, bir tür özelliği aşağıdakilerden oluşan anonim türüdür Parent
ve tip bir özelliği IEnumerable<Child>
. Bu sorgu sözdizimi GroupJoin
başlık altındaki yöntemi kullanır .
Biz sadece yapabileceği select g
bir seçersiniz ikinci sorguda, içinde IEnumerable<IEnumerable<Child>>
, listelerin listesi söylüyorlar. Çoğu durumda, ebeveynin dahil olduğu seçim daha yararlıdır.
Bazı kullanım durumları
1. Düz bir dış birleşim oluşturmak.
Dediğim gibi, açıklama ...
from p in Parent
join c in Child on p.Id equals c.Id into g
select new { Parent = p, Children = g }
... çocuk gruplarına sahip bir ebeveyn listesi oluşturur. Bu, iki küçük ilavelerle düz bir ebeveyn-çocuk çifti listesine dönüştürülebilir:
from p in parents
join c in children on p.Id equals c.Id into g // <= into
from c in g.DefaultIfEmpty() // <= flattens the groups
select new { Parent = p.Value, Child = c?.ChildValue }
Sonuç şuna benzer
Value Child
A a1
A a2
A a3
B b1
B b2
C (null)
Aralık değişkeninin c
yukarıdaki ifadede yeniden kullanıldığını unutmayın . Bunu yaparak, herhangi bir join
açıklama basitçe bir dönüştürülmüş olabilir outer join
eşdeğer ekleyerek into g from c in g.DefaultIfEmpty()
varolan için join
deyimi.
Bu, sorgu (veya kapsamlı) sözdiziminin parladığı yerdir. Yöntem (veya akıcı) sözdizimi gerçekten ne olduğunu gösterir, ancak yazmak zor:
parents.GroupJoin(children, p => p.Id, c => c.Id, (p, c) => new { p, c })
.SelectMany(x => x.c.DefaultIfEmpty(), (x,c) => new { x.p.Value, c?.ChildValue } )
Yani outer join
LINQ'da bir daire GroupJoin
, düzleştirilmiş bir SelectMany
.
2. sipariş koruma
Ebeveyn listesinin biraz daha uzun olduğunu varsayalım. Bazı kullanıcı arabirimleri, seçilen ana öğelerin listesini Id
sabit bir sırada değerler olarak üretir . Kullanalım:
var ids = new[] { 3,7,2,4 };
Şimdi seçilen ebeveynler ebeveyn listesinden bu sırayla filtrelenmelidir.
Eğer yaparsak ...
var result = parents.Where(p => ids.Contains(p.Id));
... sonucu sırası parents
belirleyecektir. Ebeveynler tarafından sipariş edilirse, Id
sonuç ebeveynler 2, 3, 4, 7 olacaktır. İyi değil. Ancak, join
listeyi filtrelemek için de kullanabiliriz . Ve ids
ilk liste olarak kullanarak , sipariş korunacaktır:
from id in ids
join p in parents on id equals p.Id
select p
Sonuç ebeveynler 3, 7, 2, 4'tür.