LINQ Bergabung dengan Berbagai Ketentuan di On Clause

94

Saya mencoba menerapkan kueri di LINQ yang menggunakan gabungan luar kiri dengan beberapa kondisi di klausa ON.

Saya akan menggunakan contoh dua tabel berikut Project (ProjectID, ProjectName) dan Task (TaskID, ProjectID, TaskName, Completed). Saya ingin melihat daftar lengkap semua proyek dengan tugasnya masing-masing, tetapi hanya tugas yang sudah selesai.

Saya tidak dapat menggunakan filter Completed == truekarena itu akan menyaring proyek yang tidak menyelesaikan tugas. Sebagai gantinya saya ingin menambahkan Completed == trueklausa ON dari join sehingga daftar lengkap proyek akan ditampilkan, tetapi hanya tugas yang sudah selesai yang akan ditampilkan. Proyek tanpa tugas yang diselesaikan akan menampilkan satu baris dengan nilai null untuk Tugas.

Inilah dasar dari kueri tersebut.

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 }

Bagaimana cara menambahkan && t2.Completed == trueklausa on?

Sepertinya saya tidak dapat menemukan dokumentasi LINQ tentang cara melakukan ini.

Kuyenda
sumber
Jawaban terkait di sini menggunakan sintaks Lambda
StuartLC

Jawaban:

132

Anda hanya perlu memberi nama properti anonim yang sama di kedua sisi

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

Berdasarkan komentar @svick, berikut adalah implementasi lain yang mungkin lebih masuk akal:

from t1 in Projects
from t2 in Tasks.Where(x => t1.ProjectID == x.ProjectID && x.Completed == true)
                .DefaultIfEmpty()
select new { t1.ProjectName, t2.TaskName }
Aducci
sumber
2
Itu sepertinya cara yang tidak jelas untuk melakukan itu. Saya tidak yakin saya akan mengerti apa yang seharusnya dilakukan.
svick
1
@svick - Menggunakan tipe anonim memungkinkan Anda untuk bergabung dalam beberapa kriteria. Anda hanya perlu memastikan nama properti cocok di kedua jenis. Tidak yakin dari mana datangnya kebingungan?
Aducci
Kebingungannya adalah bahwa itu benar-benar lebih masuk akal karena dua persamaan digabungkan and, bukan satu persamaan dari beberapa objek "aneh". Dan untuk membuktikan maksud saya, kode Anda salah. Agar berhasil, Anda harus memiliki truedi sisi kiri dan t2.Completedi kanan.
svick
1
Terima kasih Aducci. Saya harus menukar sisi dalam kueri untuk mendapatkan konteks yang benar, tetapi itu berhasil. Masalah ini disederhanakan, dan dalam masalah dunia nyata saya bukan hanya SecondProperty benar atau salah, SecondProperty adalah integer dan saya gunakan AND SecondProperty IN (123, 456). Saya akan melanjutkan ke tantangan itu dan bantuan apa pun yang dapat Anda berikan akan sangat dihargai.
Kuyenda
@svick - Tangkapan yang bagus, saya mengganti urutan t2.Completed dan nilai sebenarnya . Saya menambahkan solusi lain yang mungkin kurang aneh untuk Anda.
Aducci
40

Ini dia:

from b in _dbContext.Burden 
join bl in _dbContext.BurdenLookups on
new { Organization_Type = b.Organization_Type_ID, Cost_Type = b.Cost_Type_ID } equals
new { Organization_Type = bl.Organization_Type_ID, Cost_Type = bl.Cost_Type_ID }
Nalan Madheswaran
sumber
Ini terlihat lebih bisa dimengerti.
Bijay Yadav
1

Anda tidak bisa melakukannya seperti itu. The joinayat (dan Join()metode ekstensi) hanya mendukung equijoins. Itu juga alasannya, kenapa digunakan equalsdan tidak ==. Dan bahkan jika Anda bisa melakukan sesuatu seperti itu, itu tidak akan berhasil, karena joinitu gabungan dalam, bukan gabungan luar.

svick.dll
sumber
Gabung luar tidak diminta, dan (lihat jawaban lain), jelas Anda bisa.
edc65
0

Ini berfungsi dengan baik untuk 2 tabel. Saya memiliki 3 tabel dan pada klausul harus menghubungkan 2 kondisi dari 3 tabel. Kode saya:

dari p di _dbContext.Products gabung pv di _dbContext.ProductVariants di p.ProduktId sama dengan pv.ProduktId gabung jpr di leftJoinQuery di baru {VariantId = pv.Vid, ProductId = p.ProduktId} sama dengan baru {VariantId = jpr.Prices.VariantID, ProductId = jpr.Prices.ProduktID} ke lj

Tapi itu menunjukkan kesalahan pada titik ini: gabung pv di _dbContext.ProductVariants di p.ProduktId sama dengan pv.ProduktId

Kesalahan: Jenis salah satu ekspresi dalam klausa gabungan salah. Jenis inferensi gagal dalam panggilan ke 'GroupJoin'.

OracleNovice
sumber