2009-08-06 29 views
6

Câu hỏi này theo sau từ một số question Tôi đã hỏi ngày hôm qua về lý do tại sao sử dụng truy vấn tham gia trên các thực thể của tôi tạo ra SQL phức tạp khủng khiếp. Dường như thực hiện một truy vấn như thế này:Sự khác nhau giữa việc sử dụng Tham gia trong LINQ và "Phong cách Olde" trước cú pháp tham gia ANSI là gì?

 var query = from ev in genesisContext.Events 
        join pe in genesisContext.People_Event_Link 
        on ev equals pe.Event 
        where pe.P_ID == key 
        select ev; 

Được sản xuất các SQL khủng khiếp mà mất 18 giây để chạy trên cơ sở dữ liệu, trong khi tham gia các thực thể thông qua một mệnh đề where (loại giống như trước ANSI-cú pháp SQL) mất ít hơn một giây để chạy và sản xuất cùng một kết quả

 var query = from pe in genesisContext.People_Event_Link 
        from ev in genesisContext.Events 
        where pe.P_ID == key && pe.Event == ev 
        select ev; 

Tôi đã googled tất cả nhưng vẫn không hiểu tại sao thứ hai lại tạo ra SQL khác nhau cho lần đầu tiên. Ai đó có thể giải thích sự khác biệt với tôi không? Khi nào tôi nên sử dụng tham gia khóa


Đây là SQL đã được tạo ra khi tôi đã sử dụng Tham gia trong truy vấn của tôi và mất 18 giây để chạy:

SELECT 
1 AS [C1], 
[Extent1].[E_ID] AS [E_ID], 
[Extent1].[E_START_DATE] AS [E_START_DATE], 
[Extent1].[E_END_DATE] AS [E_END_DATE], 
[Extent1].[E_COMMENTS] AS [E_COMMENTS], 
[Extent1].[E_DATE_ADDED] AS [E_DATE_ADDED], 
[Extent1].[E_RECORDED_BY] AS [E_RECORDED_BY], 
[Extent1].[E_DATE_UPDATED] AS [E_DATE_UPDATED], 
[Extent1].[E_UPDATED_BY] AS [E_UPDATED_BY], 
[Extent1].[ET_ID] AS [ET_ID], 
[Extent1].[L_ID] AS [L_ID] 
FROM [dbo].[Events] AS [Extent1] 
INNER JOIN [dbo].[People_Event_Link] AS [Extent2] ON EXISTS (SELECT 
    1 AS [C1] 
    FROM (SELECT 1 AS X) AS [SingleRowTable1] 
    LEFT OUTER JOIN (SELECT 
      [Extent3].[E_ID] AS [E_ID] 
     FROM [dbo].[Events] AS [Extent3] 
     WHERE [Extent2].[E_ID] = [Extent3].[E_ID]) AS [Project1] ON 1 = 1 
    LEFT OUTER JOIN (SELECT 
     [Extent4].[E_ID] AS [E_ID] 
     FROM [dbo].[Events] AS [Extent4] 
     WHERE [Extent2].[E_ID] = [Extent4].[E_ID]) AS [Project2] ON 1 = 1 
    WHERE ([Extent1].[E_ID] = [Project1].[E_ID]) OR (([Extent1].[E_ID] IS NULL) AND ([Project2].[E_ID] IS NULL)) 
) 
WHERE [Extent2].[P_ID] = 291 

Đây là SQL được sản xuất bằng cách sử dụng cú pháp Kiểu ANSI (và khá gần với những gì tôi sẽ viết nếu tôi đang viết bản thân SQL):

SELECT * FROM Events AS E INNER JOIN People_Event_Link AS PE ON E.E_ID=PE.E_ID INNER JOIN PEOPLE AS P ON P.P_ID=PE.P_ID 
WHERE P.P_ID = 291 
+0

Câu hỏi hay. – tomfanning

+0

Bạn đang sử dụng DB nào? Mã SQL trông như thế nào? – AnthonyWJones

Trả lời

4

Cả các truy vấn trên đều hoàn toàn "đúng". Trong EF, nói chung là đúng để sử dụng các thuộc tính mối quan hệ thay cho một trong hai điều trên. Ví dụ, nếu bạn đã có một đối tượng Person với một đến nhiều mối quan hệ với PHONENUMBERS trong một tài sản được gọi Person.PhoneNumbers, bạn có thể viết:

var q = from p in Context.Person 
     from pn in p.PhoneNumbers 
     select pn; 

EF sẽ xây dựng tham gia cho bạn.

Về mặt câu hỏi trên, lý do SQL được tạo khác nhau là do các cây biểu thức khác nhau, mặc dù chúng tạo ra kết quả tương đương. Cây biểu thức được ánh xạ tới SQL, và dĩ nhiên bạn biết rằng bạn có thể viết các SQL khác nhau tạo ra cùng một kết quả nhưng với hiệu năng khác nhau. Ánh xạ được thiết kế để tạo ra SQL phong nha khi bạn viết một truy vấn EF "thông thường".

Nhưng ánh xạ không thông minh như vậy để có một truy vấn rất độc đáo và tối ưu hóa nó. Trong truy vấn đầu tiên của bạn, bạn tuyên bố rằng các đối tượng phải tương đương. Trong trường hợp thứ hai, bạn tuyên bố rằng thuộc tính ID ID phải tương đương. Truy vấn mẫu của tôi ở trên nói "chỉ nhận được chi tiết cho bản ghi này". EF được thiết kế để hoạt động theo cách tôi thể hiện, chủ yếu, nhưng cũng xử lý tốt tương đương vô hướng.

+0

Cuối cùng, nó làm việc và hiểu rõ hơn một chút những gì tôi đang cố gắng làm - cảm ơn. – Calanus

Các vấn đề liên quan