LINQ Tham gia với nhiều điều kiện trong điều khoản


93

Tôi đang cố gắng triển khai một truy vấn trong LINQ sử dụng kết nối bên ngoài bên trái với nhiều điều kiện trong mệnh đề ON.

Tôi sẽ sử dụng ví dụ về hai bảng sau đây Dự án (ProjectID, ProjectName) và Tác vụ (TaskID, ProjectID, TaskName, Hoàn thành). Tôi muốn xem danh sách đầy đủ của tất cả các dự án với các nhiệm vụ tương ứng của chúng, nhưng chỉ những nhiệm vụ đã hoàn thành.

Tôi không thể sử dụng bộ lọc Completed == truevì điều đó sẽ lọc ra bất kỳ dự án nào không có nhiệm vụ đã hoàn thành. Thay vào đó, tôi muốn thêm Completed == truevào điều khoản BẬT của phép nối để danh sách đầy đủ các dự án sẽ được hiển thị, nhưng chỉ các nhiệm vụ đã hoàn thành mới được hiển thị. Các dự án không có nhiệm vụ đã hoàn thành sẽ hiển thị một hàng có giá trị null cho Nhiệm vụ.

Đây là nền tảng của truy vấn.

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 }

Làm cách nào để thêm && t2.Completed == truevào mệnh đề on?

Tôi dường như không thể tìm thấy bất kỳ tài liệu LINQ nào về cách thực hiện việc này.


Câu trả lời liên quan ở đây bằng cách sử dụng cú pháp Lambda
StuartLC

Câu trả lời:


130

Bạn chỉ cần đặt tên cho tài sản ẩn danh giống nhau ở cả hai bên

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

Dựa trên nhận xét của @svick, đây là một cách triển khai khác có thể có ý nghĩa hơn:

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
Đó có vẻ như là một cách không rõ ràng để làm điều đó. Tôi không chắc mình sẽ hiểu những gì được cho là phải làm.
svick

1
@svick - Sử dụng các loại ẩn danh cho phép bạn tham gia theo nhiều tiêu chí. Bạn chỉ cần đảm bảo rằng tên thuộc tính khớp trên cả hai loại. Không chắc sự nhầm lẫn đến từ đâu?
Aducci

Sự nhầm lẫn là nó thực sự có ý nghĩa hơn khi hai bằng nhau được nối với nhau and, chứ không phải một bằng nhau của một số đối tượng "kỳ lạ". Và để chứng minh quan điểm của tôi, mã của bạn là sai. Để nó hoạt động, bạn sẽ phải có trueở bên trái và t2.Completebên phải.
svick

1
Cảm ơn Aducci. Tôi đã phải hoán đổi các bên trong truy vấn để làm đúng ngữ cảnh, nhưng điều đó đã hoạt động. Vấn đề này được đơn giản hóa, và trong thế giới thực của tôi, vấn đề không chỉ là SecondProperty đúng hay sai, SecondProperty là một số nguyên và tôi sử dụng AND SecondProperty IN (123, 456). Tôi sẽ tiếp tục thử thách đó và bất kỳ sự giúp đỡ nào bạn có thể cung cấp sẽ được đánh giá rất cao.
Kuyenda

@svick - Bắt tốt, tôi đã chuyển thứ tự của t2. Hoàn thành và giá trị thực . Tôi đã thêm một giải pháp khác có thể ít kỳ lạ hơn cho bạn.
Aducci

39

Ở đây bạn đi với:

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 }

Điều này có vẻ dễ hiểu hơn.
Bijay Yadav

1

Bạn không thể làm điều đó như vậy. Các joinkhoản (và các Join()phương pháp khuyến nông) chỉ hỗ trợ equijoins. Đó cũng là lý do, tại sao nó sử dụng equalsvà không ==. Và ngay cả khi bạn có thể làm điều gì đó như vậy, nó sẽ không hoạt động, bởi vì joinnó là một liên kết bên trong, không phải liên kết bên ngoài.


Tham gia bên ngoài không được yêu cầu và (xem các câu trả lời khác), rõ ràng là bạn có thể.
edc65

0

Điều này hoạt động tốt cho 2 bảng. Tôi có 3 bảng và điều khoản trên phải liên kết 2 điều kiện từ 3 bảng. Mã của tôi:

từ p trong _dbContext. Sản phẩm tham gia pv trong _dbContext.ProductVariants trên p.ProduktId bằng pv.ProduktId tham gia jpr ở leftJoinQuery trên mới {VariantId = pv.Vid, ProductId = p.ProduktId} bằng mới {VariantId, jprices.Variantr.Prices. ProductId = jpr.Prices.ProduktID} thành lj

Nhưng lỗi hiển thị của nó tại thời điểm này: tham gia pv trong _dbContext.ProductVariants trên p.ProduktId bằng pv.ProduktId

Lỗi: Loại của một trong các biểu thức trong mệnh đề nối không chính xác. Nhập suy luận không thành công trong lệnh gọi 'GroupJoin'.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.