2011-12-18 61 views
1

在使用Entity Framework v.X三年後,今天我看到EF4有一個奇怪的行爲。 事實是:實體框架4和T-SQL查詢結果不匹配

在數據庫AdventureWork,我執行以下命令:

var query = (ObjectQuery) context.Products.Select(p => p.ProductDocuments.Where(c => c.ProductID == p.ProductID)); 
Console.WriteLine(query.ToTraceString()); 

ToTraceSstring()顯示將要執行的實際查詢:

SELECT 
[Project1].[ProductID] AS [ProductID], 
[Project1].[C1] AS [C1], 
[Project1].[ProductID1] AS [ProductID1], 
[Project1].[DocumentID] AS [DocumentID], 
[Project1].[ModifiedDate] AS [ModifiedDate] 
FROM (SELECT 
     [Extent1].[ProductID] AS [ProductID], 
     [Extent2].[ProductID] AS [ProductID1], 
     [Extent2].[DocumentID] AS [DocumentID], 
     [Extent2].[ModifiedDate] AS [ModifiedDate], 
     CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 
END AS [C1] 
     FROM [Production].[Product] AS [Extent1] 
     LEFT OUTER JOIN [Production].[ProductDocument] AS [Extent2] ON ([Extent1].[ProductID] = [Extent2].[ProductID]) AND ([Extent2].[ProductID] = [Extent1].[ProductID]) 
) AS [Project1] 
ORDER BY [Project1].[ProductID] ASC, [Project1].[C1] ASC 

一旦從SSMS執行,它顯示505行。

但是,當我嘗試從EF執行:

var query= context.Products.Select(p => p.ProductDocuments.Where(c => c.ProductID == p.ProductID)); 
Console.WriteLine(query.Count()); 

它只會返回504行。

比較結果後,似乎ProductDocument中有兩行具有相同的ProductID = 506,這是完全正常的。這些重複的行只被檢索一次,而不是預期的兩倍。

這個問題的任何想法?

回答

1

你是正確的,在你的lambda表達式的天真解釋將意味着你只是要求:

SELECT Products.* 
FROM Products 
INNER JOIN ProductDocuments 
    ON ProductDocuments.ProductID = Products.ProductID 

,並且不是得到:

SELECT DISTINCT Products.* 
FROM Products 
INNER JOIN ProductDocuments 
    ON ProductDocuments.ProductID = Products.ProductID 

但是,你確定您發佈的SQL是您的代碼的結果,因爲SQL正在返回文檔的某些部分,而您的代碼正在請求產品實體?當然,對於一組產品來說,返回重複的實體將毫無意義且不正確。

1

SQL是正確的。預計在該請求中會出現左外連接。

但現在的問題是爲什麼查詢結果不一樣。有沒有從ToTraceString()虛擬的解釋?我現在使用反射器在閱讀IQueryable時對導航的看法有一個最接近的看法