ฉันค้นเว็บแล้ว แต่ฉันยังหาคำตอบง่าย ๆ ไม่ได้ มีคนช่วยอธิบายด้วยภาษาอังกฤษง่ายๆGroupJoin
ได้ไหม? มันแตกต่างจากภายในทั่วไปJoin
อย่างไร ใช้บ่อยไหม มันเป็นเพียงไวยากรณ์ของวิธีการ? สิ่งที่เกี่ยวกับไวยากรณ์แบบสอบถาม ตัวอย่างรหัส c # น่าจะดี
ฉันค้นเว็บแล้ว แต่ฉันยังหาคำตอบง่าย ๆ ไม่ได้ มีคนช่วยอธิบายด้วยภาษาอังกฤษง่ายๆGroupJoin
ได้ไหม? มันแตกต่างจากภายในทั่วไปJoin
อย่างไร ใช้บ่อยไหม มันเป็นเพียงไวยากรณ์ของวิธีการ? สิ่งที่เกี่ยวกับไวยากรณ์แบบสอบถาม ตัวอย่างรหัส c # น่าจะดี
คำตอบ:
สมมติว่าคุณมีสองรายการ:
Id Value
1 A
2 B
3 C
Id ChildValue
1 a1
1 a2
1 a3
2 b1
2 b2
เมื่อคุณJoin
ทั้งสองรายการในId
สนามผลลัพธ์จะเป็น:
Value ChildValue
A a1
A a2
A a3
B b1
B b2
เมื่อคุณGroupJoin
ทั้งสองรายการในId
สนามผลลัพธ์จะเป็น:
Value ChildValues
A [a1, a2, a3]
B [b1, b2]
C []
ดังนั้นJoin
สร้างผลลัพธ์แบบแบน (ตาราง) ของค่าหลักและค่ารอง
GroupJoin
สร้างรายการของรายการในรายการแรกแต่ละรายการมีกลุ่มของรายการที่เข้าร่วมในรายการที่สอง
นั่นเป็นเหตุผลที่Join
เทียบเท่าของINNER JOIN
ใน SQL: C
มีรายการไม่ while GroupJoin
มีค่าเท่ากับOUTER JOIN
: C
อยู่ในชุดผลลัพธ์ แต่มีรายการว่างของรายการที่เกี่ยวข้อง (ในชุดผลลัพธ์ SQL จะมีแถวC - null
)
ดังนั้นให้ทั้งสองรายการเป็นIEnumerable<Parent>
และIEnumerable<Child>
ตามลำดับ (ในกรณีของการ Linq เพื่อองค์กร: IQueryable<T>
)
Join
ไวยากรณ์จะเป็น
from p in Parent
join c in Child on p.Id equals c.Id
select new { p.Value, c.ChildValue }
ส่งคืนIEnumerable<X>
ที่ X เป็นประเภทที่ไม่ระบุชื่อที่มีสองคุณสมบัติและValue
ChildValue
ไวยากรณ์เคียวรีนี้ใช้Join
เมธอดภายใต้ประทุน
GroupJoin
ไวยากรณ์จะเป็น
from p in Parent
join c in Child on p.Id equals c.Id into g
select new { Parent = p, Children = g }
กลับโดยIEnumerable<Y>
ที่ Y เป็นประเภทที่ไม่ระบุตัวตนประกอบด้วยคุณสมบัติประเภทหนึ่งParent
และคุณสมบัติประเภทIEnumerable<Child>
หนึ่ง ไวยากรณ์เคียวรีนี้ใช้GroupJoin
เมธอดภายใต้ประทุน
เราสามารถทำได้select g
ในการสืบค้นหลังซึ่งจะเลือกรายการIEnumerable<IEnumerable<Child>>
พูดรายการ ในหลายกรณีการเลือกที่มีพาเรนต์รวมอยู่จะมีประโยชน์มากกว่า
ดังที่กล่าวไว้คำสั่ง ...
from p in Parent
join c in Child on p.Id equals c.Id into g
select new { Parent = p, Children = g }
... สร้างรายชื่อผู้ปกครองที่มีกลุ่มลูก สิ่งนี้สามารถเปลี่ยนเป็นรายการแบบแบนของคู่พาเรนต์ - ชายโดยการเพิ่มขนาดเล็กสองรายการ:
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 }
ผลลัพธ์จะคล้ายกับ
Value Child
A a1
A a2
A a3
B b1
B b2
C (null)
โปรดทราบว่าตัวแปรช่วง c
จะถูกใช้ซ้ำในคำสั่งด้านบน การทำเช่นนี้join
คำสั่งใด ๆสามารถถูกแปลงเป็น a ได้outer join
โดยการเพิ่มคำสั่งที่เทียบเท่าinto g from c in g.DefaultIfEmpty()
กับjoin
คำสั่งที่มีอยู่
นี่คือที่การสืบค้น (หรือครอบคลุม) ไวยากรณ์ส่อง ไวยากรณ์ของเมธอด (หรือคล่องแคล่ว) แสดงให้เห็นว่าเกิดอะไรขึ้นจริง แต่ยากที่จะเขียน:
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 } )
ดังนั้นแบนouter join
ใน LINQ เป็นแบนโดยGroupJoin
SelectMany
สมมติว่ารายชื่อผู้ปกครองนั้นมีความยาวขึ้นอีกเล็กน้อย UI บางรายการสร้างรายการของพาเรนต์ที่เลือกเป็นId
ค่าในลำดับคงที่ มาใช้กัน:
var ids = new[] { 3,7,2,4 };
ตอนนี้ผู้ปกครองที่เลือกจะต้องถูกกรองออกจากรายการผู้ปกครองในลำดับที่แน่นอนนี้
ถ้าเราทำ ...
var result = parents.Where(p => ids.Contains(p.Id));
... ลำดับของparents
จะเป็นตัวกำหนดผลลัพธ์ หากผู้ปกครองได้รับคำสั่งId
ผลที่ได้คือผู้ปกครอง 2, 3, 4, 7 ไม่ดี อย่างไรก็ตามเรายังสามารถใช้join
ในการกรองรายการ และโดยใช้ids
เป็นรายการแรกคำสั่งซื้อจะถูกเก็บไว้:
from id in ids
join p in parents on id equals p.Id
select p
ผลลัพธ์คือผู้ปกครอง 3, 7, 2, 4
ตามeduLINQ :
วิธีที่ดีที่สุดในการเข้าถึงสิ่งที่ GroupJoin ทำคือคิดถึงการเข้าร่วม ที่นั่นแนวคิดโดยรวมคือเรามองผ่านลำดับการป้อนข้อมูล "ด้านนอก" พบรายการที่ตรงกันทั้งหมดจากลำดับ "ภายใน" (ขึ้นอยู่กับการคาดการณ์ที่สำคัญในแต่ละลำดับ) จากนั้นให้คู่ขององค์ประกอบการจับคู่ GroupJoin คล้ายยกเว้นว่าแทนที่จะยอมคู่ขององค์ประกอบก็มีผลเป็นผลเดี่ยวสำหรับแต่ละรายการ "นอก" ขึ้นอยู่กับสินค้าที่และลำดับของการจับคู่รายการ
ความแตกต่างเพียงอย่างเดียวคือข้อความสั่งคืน:
เข้าร่วม :
var lookup = inner.ToLookup(innerKeySelector, comparer);
foreach (var outerElement in outer)
{
var key = outerKeySelector(outerElement);
foreach (var innerElement in lookup[key])
{
yield return resultSelector(outerElement, innerElement);
}
}
กลุ่มงาน :
var lookup = inner.ToLookup(innerKeySelector, comparer);
foreach (var outerElement in outer)
{
var key = outerKeySelector(outerElement);
yield return resultSelector(outerElement, lookup[key]);
}
อ่านเพิ่มเติมได้ที่นี่: