使用Entity Framework v.X三年后,今天我看到了EF4的奇怪行为。 事实是:
在数据库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,这是完全正常的。那些重复的行只被检索一次而不是预期的两次。
对这个问题有任何想法吗?
答案 0 :(得分: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 :(得分:1)
SQL是正确的。并且在该请求中预期LEFT OUTER JOIN。
但问题是现在查询结果不一样的原因。 ToTraceString()
是否存在虚拟解释?我现在使用反射器来仔细查看导航在阅读IQueryable时的方式