2009-03-31 46 views
121

Truy vấn này có tương đương với LEFT OUTER tham gia không?LINQ to SQL External Outer Tham gia

//assuming that I have a parameter named 'invoiceId' of type int 
from c in SupportCases 
let invoice = c.Invoices.FirstOrDefault(i=> i.Id == invoiceId) 
where (invoiceId == 0 || invoice != null)  
select new 
{ 
     Id = c.Id 
     , InvoiceId = invoice == null ? 0 : invoice.Id 
} 

Trả lời

141

Không hẳn - vì mỗi "trái" hàng trong một trái ngoài-tham gia sẽ phù hợp với 0-n "đúng" hàng (trong bảng thứ hai), nơi-như bạn chỉ 0-1 phù hợp. Để làm được một trái bên ngoài tham gia, bạn cần SelectManyDefaultIfEmpty, ví dụ:

var query = from c in db.Customers 
      join o in db.Orders 
       on c.CustomerID equals o.CustomerID into sr 
      from x in sr.DefaultIfEmpty() 
      select new { 
       CustomerID= c.CustomerID, ContactName=c.ContactName, 
       OrderID = x.OrderID == null ? -1 : x.OrderID}; 

(or via the extension methods)

+4

LINQ to Entities không nhận ra phương thức DefaultIfEmpty ... –

+13

Ai đó có thể giải thích cách cú pháp này hoạt động như thế nào? Tôi không thấy làm thế nào bất kỳ của những từ khóa kỳ diệu làm cho nó một tham gia trái. Những gì hiện "vào sr" làm gì? Linq làm tôi thất vọng đôi khi :) –

+1

@JoePhillips Tôi có rất nhiều kinh nghiệm về SQL nhưng cố gắng tìm hiểu LINQ giống như lội qua bùn. Tôi đồng ý nó hoàn toàn điên rồ. –

12
Public Sub LinqToSqlJoin07() 
Dim q = From e In db.Employees _ 
     Group Join o In db.Orders On e Equals o.Employee Into ords = Group _ 
     From o In ords.DefaultIfEmpty _ 
     Select New With {e.FirstName, e.LastName, .Order = o} 

ObjectDumper.Write(q) End Sub 

Kiểm tra http://msdn.microsoft.com/en-us/vbasic/bb737929.aspx

+0

Thử tốt nhưng có vẻ như OP đang sử dụng C#. Cú pháp VB khác lạ. – Levitikon

+3

+1 Đơn giản vì đây là ví dụ vb.net tốt – twoleggedhorse

4

tôi thấy 1 giải pháp. nếu muốn dịch loại này của SQL (trái tham gia) vào LINQ Entity ...

SQL:

SELECT * FROM [JOBBOOKING] AS [t0] 
LEFT OUTER JOIN [REFTABLE] AS [t1] ON ([t0].[trxtype] = [t1].[code]) 
            AND ([t1]. [reftype] = "TRX") 

LINQ:

from job in JOBBOOKINGs 
join r in (from r1 in REFTABLEs where r1.Reftype=="TRX" select r1) 
      on job.Trxtype equals r.Code into join1 
from j in join1.DefaultIfEmpty() 
select new 
{ 
    //cols... 
} 
+0

Xem [bình luận này] (http://stackoverflow.com/questions/700523/linq-to-sql-left-outer-join#comment21835463_700580), Linq-to Các thực thể -SQL không hỗ trợ 'DefaultIfEmpty'. –

177

Bạn không cần phải vào báo cáo:

var query = 
    from customer in dc.Customers 
    from order in dc.Orders 
     .Where(o => customer.CustomerId == o.CustomerId) 
     .DefaultIfEmpty() 
    select new { Customer = customer, Order = order } 
    //Order will be null if the left join is null 

Và có, truy vấn ở trên thực sự tạo LEFT OUTER join .

Liên kết đến một câu hỏi tương tự để xử lý nhiều trái tham gia: Linq to Sql: Multiple left outer joins

+10

Trong khi tôi biết rằng câu trả lời của @Marc Gravvel không hoạt động, tôi thực sự thích phương pháp này vì IMO nó cảm thấy phù hợp hơn với những gì một bên trái tham gia như thế nào. – llaughlin

+1

Câu trả lời hay. Tìm kiếm hơn 5 giờ tìm kiếm trên google. Đây là cách duy nhất kết quả SQL sẽ để lại tham gia vào nó. –

+1

THANK YOU soooo nhiều .... Tôi đã tìm kiếm một giải pháp cho tất cả các buổi chiều và mã của bạn đóng đinh nó (và cảm thấy tự nhiên để khởi động). Ước gì tôi có thể upvote điều này nhiều lần. – Jim

1

Tôi muốn thêm một điều nữa. Trong LINQ to SQL nếu DB của bạn được xây dựng đúng và các bảng của bạn có liên quan thông qua các ràng buộc khóa ngoài, thì bạn không cần phải tham gia vào tất cả.

Sử dụng LINQPad tôi tạo ra các truy vấn sau đây LINQ:

//Querying from both the CustomerInfo table and OrderInfo table 
from cust in CustomerInfo 
where cust.CustomerID == 123456 
select new {cust, cust.OrderInfo} 

nào được dịch sang (hơi cắt ngắn) truy vấn dưới đây Chú ý

-- Region Parameters 
DECLARE @p0 Int = 123456 
-- EndRegion 
SELECT [t0].[CustomerID], [t0].[AlternateCustomerID], [t1].[OrderID], [t1].[OnlineOrderID], (
    SELECT COUNT(*) 
    FROM [OrderInfo] AS [t2] 
    WHERE [t2].[CustomerID] = [t0].[CustomerID] 
    ) AS [value] 
FROM [CustomerInfo] AS [t0] 
LEFT OUTER JOIN [OrderInfo] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID] 
WHERE [t0].[CustomerID] = @p0 
ORDER BY [t0].[CustomerID], [t1].[OrderID] 

các LEFT OUTER JOIN trên.