เนื่องจากสิ่งนี้ดูเหมือนจะเป็นคำถามของพฤตินัย SO สำหรับการเข้าร่วมด้านนอกโดยใช้ไวยากรณ์ (ส่วนขยาย) ฉันคิดว่าฉันจะเพิ่มทางเลือกให้กับคำตอบที่เลือกในปัจจุบันที่ (ในประสบการณ์ของฉันอย่างน้อย) เป็นสิ่งที่ฉัน หลังจาก
// Option 1: Expecting either 0 or 1 matches from the "Right"
// table (Bars in this case):
var qry = Foos.GroupJoin(
Bars,
foo => foo.Foo_Id,
bar => bar.Foo_Id,
(f,bs) => new { Foo = f, Bar = bs.SingleOrDefault() });
// Option 2: Expecting either 0 or more matches from the "Right" table
// (courtesy of currently selected answer):
var qry = Foos.GroupJoin(
Bars,
foo => foo.Foo_Id,
bar => bar.Foo_Id,
(f,bs) => new { Foo = f, Bars = bs })
.SelectMany(
fooBars => fooBars.Bars.DefaultIfEmpty(),
(x,y) => new { Foo = x.Foo, Bar = y });
หากต้องการแสดงความแตกต่างโดยใช้ชุดข้อมูลแบบง่าย (สมมติว่าเราเข้าร่วมกับค่าต่างๆด้วยตนเอง):
List<int> tableA = new List<int> { 1, 2, 3 };
List<int?> tableB = new List<int?> { 3, 4, 5 };
// Result using both Option 1 and 2. Option 1 would be a better choice
// if we didn't expect multiple matches in tableB.
{ A = 1, B = null }
{ A = 2, B = null }
{ A = 3, B = 3 }
List<int> tableA = new List<int> { 1, 2, 3 };
List<int?> tableB = new List<int?> { 3, 3, 4 };
// Result using Option 1 would be that an exception gets thrown on
// SingleOrDefault(), but if we use FirstOrDefault() instead to illustrate:
{ A = 1, B = null }
{ A = 2, B = null }
{ A = 3, B = 3 } // Misleading, we had multiple matches.
// Which 3 should get selected (not arbitrarily the first)?.
// Result using Option 2:
{ A = 1, B = null }
{ A = 2, B = null }
{ A = 3, B = 3 }
{ A = 3, B = 3 }
ตัวเลือกที่ 2 เป็นจริงกับคำจำกัดความการรวมภายนอกด้านนอกโดยทั่วไป แต่ตามที่ฉันกล่าวถึงก่อนหน้านี้มักจะซับซ้อนโดยไม่จำเป็นขึ้นอยู่กับชุดข้อมูล
GroupJoin
จะเข้าร่วมด้านนอกด้านซ้ายSelectMany
ส่วนที่จำเป็นเท่านั้นขึ้นอยู่กับสิ่งที่คุณต้องการเลือก