LINQ เข้าร่วมกับหลายเงื่อนไขใน On Clause


96

ฉันกำลังพยายามใช้แบบสอบถามใน LINQ ที่ใช้การรวมภายนอกด้านซ้ายที่มีหลายเงื่อนไขในส่วนคำสั่ง ON

ฉันจะใช้ตัวอย่างของสองตารางต่อไปนี้Project (ProjectID, ProjectName) และTask (TaskID, ProjectID, TaskName, Completed) ฉันต้องการดูรายการทั้งหมดของโครงการทั้งหมดที่มีงานตามลำดับ แต่เฉพาะงานที่เสร็จสมบูรณ์

ฉันไม่สามารถใช้ตัวกรองCompleted == trueเพราะจะกรองโปรเจ็กต์ใด ๆ ที่ไม่มีงานที่เสร็จสมบูรณ์ออกไป แต่ฉันต้องการเพิ่มCompleted == trueในส่วนคำสั่ง ON ของการเข้าร่วมเพื่อให้แสดงรายการโครงการทั้งหมด แต่จะแสดงเฉพาะงานที่เสร็จสมบูรณ์เท่านั้น โครงการที่ไม่มีงานที่เสร็จสมบูรณ์จะแสดงแถวเดียวพร้อมค่าว่างสำหรับงาน

นี่คือรากฐานของแบบสอบถาม

from t1 in Projects
join t2 in Tasks
on new { t1.ProjectID} equals new { t2.ProjectID } into j1
from j2 in j1.DefaultIfEmpty()
select new { t1.ProjectName, t2.TaskName }

ฉันจะเพิ่ม&& t2.Completed == trueคำสั่ง on ได้อย่างไร?

ฉันไม่พบเอกสารของ LINQ เกี่ยวกับวิธีการทำสิ่งนี้


คำตอบที่เกี่ยวข้องที่นี่โดยใช้ไวยากรณ์ Lambda
StuartLC

คำตอบ:


136

คุณเพียงแค่ต้องตั้งชื่อคุณสมบัติที่ไม่ระบุชื่อให้เหมือนกันทั้งสองด้าน

on new { t1.ProjectID, SecondProperty = true } equals 
   new { t2.ProjectID, SecondProperty = t2.Completed } into j1

จากความคิดเห็นของ @svick นี่คือการใช้งานอื่นที่อาจสมเหตุสมผลกว่า:

from t1 in Projects
from t2 in Tasks.Where(x => t1.ProjectID == x.ProjectID && x.Completed == true)
                .DefaultIfEmpty()
select new { t1.ProjectName, t2.TaskName }

2
ดูเหมือนจะเป็นวิธีที่ไม่ชัดเจนในการทำเช่นนั้น ฉันไม่แน่ใจว่าฉันจะเข้าใจสิ่งที่ควรทำ
svick

1
@svick - การใช้ประเภทที่ไม่ระบุตัวตนช่วยให้คุณสามารถเข้าร่วมในหลายเกณฑ์ได้ คุณต้องแน่ใจว่าชื่อคุณสมบัติตรงกันทั้งสองประเภท ไม่แน่ใจว่าความสับสนมาจากไหน?
Aducci

ความสับสนคือมันสมเหตุสมผลกว่าเมื่อความเท่าเทียมกันสองอย่างรวมเข้าด้วยandกันไม่ใช่ความเท่าเทียมกันของวัตถุที่ "แปลก" และเพื่อพิสูจน์ประเด็นของฉันรหัสของคุณผิด เพื่อให้ได้ผลคุณจะต้องมีtrueทางด้านซ้ายและt2.Completeทางขวา
svick

1
ขอบคุณ Aducci ฉันต้องสลับข้างในแบบสอบถามเพื่อให้บริบทถูกต้อง แต่ก็ใช้ได้ผล ปัญหานี้เป็นไปอย่างง่ายดายและในโลกแห่งความจริงปัญหาของฉันมันไม่ได้เป็นเพียง SecondProperty เป็นจริงหรือเท็จ SecondProperty AND SecondProperty IN (123, 456)เป็นจำนวนเต็มและฉันใช้ ฉันจะก้าวไปสู่ความท้าทายนั้นและความช่วยเหลือใด ๆ ที่คุณสามารถให้ได้จะได้รับการชื่นชมอย่างมาก
Kuyenda

@svick - จับได้ดีฉันเปลี่ยนลำดับของt2 เสร็จสมบูรณ์และค่าที่แท้จริง ฉันได้เพิ่มวิธีแก้ปัญหาอื่นที่อาจไม่แปลกสำหรับคุณ
Aducci


1

เธอทำแบบนั้นไม่ได้ joinข้อ (และJoin()วิธีขยาย) สนับสนุน equijoins เท่านั้น นั่นคือเหตุผลว่าทำไมถึงใช้equalsและไม่==ใช้ และแม้ว่าคุณจะทำอะไรแบบนั้นได้ แต่ก็ไม่ได้ผลเพราะjoinเป็นการรวมภายในไม่ใช่การรวมภายนอก


ไม่ได้ร้องขอการเข้าร่วมภายนอกและ (ดูคำตอบอื่น ๆ ) เห็นได้ชัดว่าคุณทำได้
edc65

0

ใช้ได้ดีสำหรับ 2 โต๊ะ ฉันมี 3 ตารางและในประโยคต้องเชื่อมโยง 2 เงื่อนไขจาก 3 ตาราง รหัสของฉัน:

จาก p ใน _dbContext.Products เข้าร่วม pv ใน _dbContext.ProductVariants บน p.ProduktId เท่ากับ pv.ProduktId เข้าร่วม jpr ใน leftJoinQuery บนใหม่ {VariantId = pv.Vid, ProductId = p.ProduktId} เท่ากับใหม่ {VariantId = jpr.Prices.VariantId ProductId = jpr.Prices.ProduktID} เป็น lj

แต่แสดงข้อผิดพลาด ณ จุดนี้: เข้าร่วม pv ใน _dbContext.ProductVariants บน p.ProduktId เท่ากับ pv.ProduktId

ข้อผิดพลาด: ประเภทของนิพจน์หนึ่งในอนุประโยคการรวมไม่ถูกต้อง การอนุมานประเภทล้มเหลวในการเรียก 'GroupJoin'


ข้อผิดพลาดนี้หมายความว่าประเภทของฟิลด์ของออบเจ็กต์ที่ไม่ระบุตัวตนแรกไม่ตรงกับฟิลด์ที่สอง ตรวจสอบว่าประเภทVariantIdเดียวกันและประเภทProductIdเดียวกัน ยกตัวอย่างเช่นมันอาจจะGuidเทียบGuid?- VariantId = (Guid?) jpr.Prices.VariantIDแล้วคุณจำเป็นต้องหล่อเหมือน
Evgeny Nozdrev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.